2009-01-18 13 views
13

Je me suis construit une classe de collection générique qui est définie comme ceci.Restreindre T à la chaîne et int?

public class StatisticItemHits<T>{...} 

Cette classe peut être utilisé avec int et string valeurs seulement. Cependant, cette

public class StatisticItemHits<T> where T : string, int {...} 

ne compilera pas. Qu'est-ce que je fais mal?

+0

Quelque chose me dit que vous faites cela parce que vous ne l'avez pas rendu compte qu'un casting implicite serait mieux ... – Will

Répondre

13

La restriction de type est destinée à être utilisée avec des interfaces. Votre exemple suggère que vous souhaitez autoriser les classes qui héritent de int et string, ce qui est un peu un non-sens. Je vous suggère de concevoir une interface qui contient les méthodes que vous utiliserez dans votre classe générique StatisticItemHits, et d'utiliser cette interface comme restriction. Cependant, je ne vois pas vraiment vos besoins ici, peut-être pourriez-vous poster plus de détails sur votre scénario?

+0

Oui, après avoir pris un second regard sur la conception, vous sont complètement à propos de votre approche. Merci de votre aide. – Mats

1

Impossible de faire cela avec 'où'. Vous ne pouvez pas faire un 'ou'.

1

Vous ne pouvez pas le restreindre à string et int à partir de la clause where. Vous pouvez le vérifier dans le constructeur, mais ce n'est probablement pas un bon endroit pour vérifier. Mon approche serait de spécialiser la classe et abstraite la création de classe en un modèle d'usine (semi-):

class MyRestrictedGeneric<T> 
{ 
    protected MyRestrictedGeneric() { } 


    // Create the right class depending on type T 
    public static MyRestrictedGeneric<T> Create<T>() 
    { 
     if (typeof(T) == typeof(string)) 
      return new StringImpl() as MyRestrictedGeneric<T>; 

     if (typeof(T) == typeof(int)) 
      return new IntImpl() as MyRestrictedGeneric<T>; 

     throw new InvalidOperationException("Type not supported"); 
    } 


    // The specialized implementation are protected away 
    protected class StringImpl : MyRestrictedGeneric<string> { } 
    protected class IntImpl : MyRestrictedGeneric<int> { } 
} 

De cette façon, vous pouvez limiter l'utilisation de la classe à chaîne juste et int interne dans votre classe.

+0

chaîne n'est pas un type de valeur .. – driAn

+0

chaîne est un type de référence, donc cela n'aide pas (je suppose) – tuinstoel

+0

Pourquoi la méthode Create accepte-t-elle un argument qui n'est jamais utilisé? – configurator

6

Vous pouvez faire StatisticItemHits<T> une classe abstraite et de créer deux sous-classes:

StatisticItemHitsInt : StatisticItemHits<int>{}

StatisticItemHitsString : StatisticItemHits<string>{}

De cette façon, il ne peut être un entier et chaîne-représentation des StatisticItemHits

3

Comme d'autres ont dit, vous ne pouvez pas utiliser les restrictions de type de cette façon. Ce que vous pouvez faire est de se spécialiser de votre type de base comme suit:

public class StatisticItemHits <T> { } 

public class StringStatisticItemHits : StatisticItemHits<string> { } 

public class IntegerStatisticItemHits : StatisticItemHits<int> { } 

De plus, en tant que votre classe de base est générique, vous ne pourrez pas l'utiliser pour polymorphically. Si vous avez besoin de faire cela, créez une interface avec StatisticItemHits et utilisez-la pour référencer les instances. Quelque chose comme:

public class StatisticItemHits <T> : IStaticticItemHits { } 

public interface IStatisticItemHits { } 
2

Étant donné que vous avez seulement deux types ici, je descendrais une route OO ici au lieu et juste deux classes pour les deux types.

Les génériques sont mieux utilisés lorsque les circonstances dans lesquelles ils peuvent être appliqués sont, vous le savez, générique. Ils sont beaucoup moins utilisés dans des circonstances comme celle-ci.

Vous pouvez limiter les types struct ou classe seulement, et je pense qu'il ya besoin d'avoir des restrictions sur la base numérique ou opérateur (par exemple, doivent prendre en charge + =)

Int et la chaîne sont vraiment tout à fait différent, certainement plus différent que int et double.Il ne serait pas logique qu'une classe générique prenne en charge le type de chaîne de référence immuable et le type de valeur de int sans prendre en charge d'autres types plus proches de l'un ou de l'autre.

-2

utiliser simplement:

where TSource : IEquatable<string>