2009-01-18 19 views
13

He creado una clase de colección genérica que se define así.Restringir T a la cadena y int?

public class StatisticItemHits<T>{...} 

Esta clase se puede utilizar con sólo int y string valores. Sin embargo, este

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

no se compilará. ¿Qué estoy haciendo mal?

+0

Algo me dice que está haciendo esto porque no se han dado cuenta de que una conversión implícita sería mejor ... – Will

Respuesta

13

La restricción de tipo está destinada a ser utilizada con interfaces. Su ejemplo sugiere que desea permitir clases que hereden de int y de la cadena, lo que es un poco absurdo. Le sugiero que diseñe una interfaz que contenga los métodos que utilizará en su clase genérica StatisticItemHits, y use esa interfaz como restricción. Sin embargo, realmente no veo sus requisitos aquí, ¿tal vez podría publicar más detalles sobre su escenario?

+0

Sí, después de tomar un segundo vistazo al diseño, se tienen toda la razón acerca de su enfoque. Gracias por tu ayuda. – Mats

1

No es posible hacer esto con 'where'. No puedes hacer un 'o'.

1

No se puede restringir a cadena e int desde la cláusula where. Puedes verificarlo en el constructor, pero probablemente este no sea un buen lugar para verificar. Mi enfoque sería especializar la clase abstracta y la creación de clases en un patrón de fábrica (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 esta manera usted puede limitar el uso de la clase que acaba de cuerda y int internamente dentro de su clase.

+0

cadena no es un tipo de valor ... – driAn

+0

cadena es un tipo de referencia, por lo que no ayuda (supongo) – tuinstoel

+0

¿Por qué el método Create acepta una arg que nunca se utiliza? – configurator

6

Se podría hacer StatisticItemHits<T> una clase abstracta y crear dos subclases:

StatisticItemHitsInt : StatisticItemHits<int>{}

StatisticItemHitsString : StatisticItemHits<string>{}

De esa manera no sólo puede ser un entero y la cadena de representación de StatisticItemHits

3

Como otros he dicho, no puedes usar restricciones de tipo de esta manera. Lo que puede hacer es la especialización de su tipo base de la siguiente manera:

public class StatisticItemHits <T> { } 

public class StringStatisticItemHits : StatisticItemHits<string> { } 

public class IntegerStatisticItemHits : StatisticItemHits<int> { } 

También, como su clase base es genérico, no será capaz de utilizar esto para polimórfica. Si necesita hacer esto, haga que StatisticItemHits implemente una interfaz y utilícela para hacer referencia a las instancias. Algo así como:

public class StatisticItemHits <T> : IStaticticItemHits { } 

public interface IStatisticItemHits { } 
2

Teniendo en cuenta que sólo tiene dos tipos aquí me gustaría ir por una ruta OO aquí en su lugar y sólo hay dos clases para los dos tipos.

Los genéricos se usan mejor cuando las circunstancias en las que se pueden aplicar son, ya sabes, generic. Son mucho menos uso en circunstancias como esta.

Puede restringir sólo a los tipos de estructura o clase, y yo creo que es necesario que existan restricciones numéricas o de servicio basados ​​(por ejemplo, deben apoyar + =)

Int y la cadena son realmente muy diferentes, sin duda, más diferente que int y doble.No tendría mucho sentido para una clase genérica admitir el tipo de referencia inmutable de cadena y el tipo de valor de int sin apoyar también otros tipos más similares a cualquiera de ellos.

-2

Utilice simplemente:

where TSource : IEquatable<string>