¿Qué significa "where T: class, new ()"?

Respuestas:

329

Esa es una restricción en el parámetro genérico T. Debe ser un class(tipo de referencia) y debe tener un constructor público predeterminado sin parámetros.

Eso significa que Tno pueden ser una int, float, double, DateTimeo cualquier otro struct(tipo de valor).

Podría ser un string, o cualquier otro tipo de referencia personalizado, siempre que tenga un constructor predeterminado o sin parámetros.

NerdFury
fuente
55
Solo para aclarar, si no tiene la cláusula de clase como parte de donde T ..., entonces es seguro usar int, float, double, etc.
AboutDev
1
@AboutDev correcto, no tiene que poner restricciones en su parámetro de tipo genérico. Pero si está creando un genérico que espera que solo funcione en tipos de referencia o de valor, debe especificarlo. Sin una restricción, puede esperar tipos de referencia (clases) o tipos de valores (estructuras (int, float, double ...)).
NerdFury
1
¿Qué pasa con T: [nombre de la interfaz], new ()? ¿Todavía necesita tener un constructor sin parámetros?
Vince Tino
3
Para aclarar el comentario de Justin, un constructor vacío no tiene declaraciones (como el constructor predeterminado) mientras que un constructor sin parámetros puede contener declaraciones (como inicializar una lista).
DharmaTurtle
@VinceTino: new()especifica con precisión "debe tener un constructor público sin parámetros"
Flater
162

Esas son restricciones de tipo genérico. En su caso hay dos de ellos:

where T : class

Significa que el tipo Tdebe ser un tipo de referencia (no un tipo de valor).

where T : new()

Significa que el tipo Tdebe tener un constructor sin parámetros. Tener esta restricción le permitirá hacer algo como T field = new T();en su código que de otra manera no podría hacer.

Luego combina los dos usando una coma para obtener:

where T : class, new()
Justin Niessner
fuente
Buenos puntos para el segundo y el tercero, solo para agregar información, creo que el segundo punto es útil cuando se hace una reflexión en tipo genérico. p.ej. T t = nuevo T (); t.GetType (). GetProperty ("ID"). SetValue (t, uniqueId, null);
Jerry Liang
1
Creo que es redundante decir dónde T: class, new (), ya que new () ya implica clase porque las estructuras no pueden tener constructores predeterminados.
DharmaTurtle
@DharmaTurtle, "las estructuras no pueden contener constructores explícitos sin parámetros", no significa que no tengan uno, dice que no se puede definir uno. fuente: msdn.microsoft.com/tr-tr/library/aa288208(v=vs.71).aspx
rustem
121

donde T: struct

El argumento de tipo debe ser un tipo de valor. Se puede especificar cualquier tipo de valor, excepto Nullable. Consulte Uso de tipos anulables (Guía de programación de C #) para obtener más información.

donde T: clase

El argumento de tipo debe ser un tipo de referencia, que incluye cualquier clase, interfaz, delegado o tipo de matriz. (Vea la nota abajo.)

donde T: new () El argumento type debe tener un constructor público sin parámetros. Cuando se usa junto con otras restricciones, la restricción new () debe especificarse en último lugar.

donde T: [nombre de la clase base]

El argumento de tipo debe ser o derivar de la clase base especificada.

donde T: [nombre de la interfaz]

El argumento de tipo debe ser o implementar la interfaz especificada. Se pueden especificar múltiples restricciones de interfaz. La interfaz de restricción también puede ser genérica.

donde T: U

El argumento de tipo proporcionado para T debe ser o derivar del argumento proporcionado para U. Esto se denomina restricción de tipo simple.

Mohammed Jubayer
fuente
23
Esto fue útil, pero enlace a la fuente .
Skean
26

class& newson 2 restricciones en el parámetro de tipo genéricoT .
Respectivamente aseguran:

class

El argumento tipo debe ser un tipo de referencia; Esto se aplica también a cualquier clase, interfaz, delegado o tipo de matriz.

new

El argumento tipo debe tener un constructor público sin parámetros. Cuando se usa junto con otras restricciones, la restricción new () debe especificarse en último lugar.

Su combinación significa que el tipo Tdebe ser un Tipo de referencia (no puede ser un Tipo de valor ) y debe tener un constructor sin parámetros.

Ejemplo:

struct MyStruct { } // structs are value types

class MyClass1 { } // no constructors defined, so the class implicitly has a parameterless one

class MyClass2 // parameterless constructor explicitly defined
{
    public MyClass2() { }
}

class MyClass3 // only non-parameterless constructor defined
{
    public MyClass3(object parameter) { }
}

class MyClass4 // both parameterless & non-parameterless constructors defined
{
    public MyClass4() { }
    public MyClass4(object parameter) { }
}

interface INewable<T>
    where T : new()
{
}

interface INewableReference<T>
    where T : class, new()
{
}

class Checks
{
    INewable<int> cn1; // ALLOWED: has parameterless ctor
    INewable<string> n2; // NOT ALLOWED: no parameterless ctor
    INewable<MyStruct> n3; // ALLOWED: has parameterless ctor
    INewable<MyClass1> n4; // ALLOWED: has parameterless ctor
    INewable<MyClass2> n5; // ALLOWED: has parameterless ctor
    INewable<MyClass3> n6; // NOT ALLOWED: no parameterless ctor
    INewable<MyClass4> n7; // ALLOWED: has parameterless ctor

    INewableReference<int> nr1; // NOT ALLOWED: not a reference type
    INewableReference<string> nr2; // NOT ALLOWED: no parameterless ctor
    INewableReference<MyStruct> nr3; // NOT ALLOWED: not a reference type
    INewableReference<MyClass1> nr4; // ALLOWED: has parameterless ctor
    INewableReference<MyClass2> nr5; // ALLOWED: has parameterless ctor
    INewableReference<MyClass3> nr6; // NOT ALLOWED: no parameterless ctor
    INewableReference<MyClass4> nr7; // ALLOWED: has parameterless ctor
}
Sergio
fuente
1
Buena demostración Gracias.
Subhan Ali
15

new (): especificar la restricción new () significa que el tipo T debe usar un constructor sin parámetros, por lo que se puede crear una instancia de un objeto a partir de él; consulte Constructores predeterminados .

clase: significa que T debe ser un tipo de referencia, por lo que no puede ser int, float, double, DateTime u otra estructura (tipo de valor).

public void MakeCars()
{
    //This won't compile as researchEngine doesn't have a public constructor and so can't be instantiated.
    CarFactory<ResearchEngine> researchLine = new CarFactory<ResearchEngine>();
    var researchEngine = researchLine.MakeEngine();

    //Can instantiate new object of class with default public constructor
    CarFactory<ProductionEngine> productionLine = new CarFactory<ProductionEngine>();
    var productionEngine = productionLine.MakeEngine();
}

public class ProductionEngine { }
public class ResearchEngine
{
    private ResearchEngine() { }
}

public class CarFactory<TEngine> where TEngine : class, new()
{
    public TEngine MakeEngine()
    {
        return new TEngine();
    }
}
Brendan
fuente
6

Eso significa que el tipo Tdebe ser una clase y tener un constructor que no tome ningún argumento.

Por ejemplo, debe poder hacer esto:

T t = new T();
Evan Mulawski
fuente
1
no solo un constructor, sino un constructor que no toma argumentos.
NerdFury
@ NerdFury: Gracias. Esa es una parte importante. Corregido
Evan Mulawski
5

donde (referencia de C #)

La nueva restricción () le permite al compilador saber que cualquier argumento de tipo proporcionado debe tener un constructor accesible sin parámetros o predeterminado

Por lo tanto, debe ser, Tdebe ser una clase y tener un constructor accesible sin parámetros o predeterminado.

Fredrik Widerberg
fuente
4

Lo que viene después del "Dónde" es una restricción sobre el tipo genérico T que declaró, así que:

  • clase significa que la T debe ser una clase y no un tipo de valor o una estructura.

  • new () indica que la clase T debe tener un constructor público predeterminado sin parámetros definido.

Otman IGHOULASSEN
fuente
1

Se llama 'restricción' en el parámetro genérico T. Significa que T debe ser un tipo de referencia (una clase) y que debe tener un constructor público predeterminado.


fuente
1

Esto es parte del mecanismo genérico, donde la palabra clave where agrega restricciones a los tipos que deben implementarse para ser utilizados como parámetros de tipo.

Peter Lillevold
fuente
0

cuando se usa la clase en restricciones, significa que solo se puede usar el tipo de Referencia, otra cosa que se debe agregar es cuándo usar la restricción new () , debe ser lo último que escriba en los términos de Restricciones.

Rebwar
fuente