Che cosa significa "dove T: class, new ()"?


Risposte:


329

Questo è un vincolo per il parametro generico T. Deve essere un class(tipo di riferimento) e deve avere un costruttore predefinito senza parametri pubblici.

Che i mezzi Tnon possono essere int, float, double, DateTimeo qualsiasi altro struct(tipo di valore).

Potrebbe essere un stringqualsiasi tipo di riferimento personalizzato, purché abbia un costruttore predefinito o senza parametri.


5
Solo per chiarire, se non hai la clausola class come parte del punto T ..., allora è sicuro usare int, float, double etc.
AboutDev

1
@AboutDev corretto, non è necessario applicare vincoli al parametro di tipo generico. Ma se si sta creando un generico che prevede di funzionare solo su tipi di riferimento o di valore, è necessario specificare. Senza un vincolo, puoi aspettarti tipi di riferimento (classi) o tipi di valore (strutture (int, float, double ...)).
NerdFury,

1
Che dire di dove T: [nome interfaccia], nuovo ()? Hai ancora bisogno di un costruttore senza parametri?
Vince Tino,

3
Per chiarire il commento di Justin, un costruttore vuoto non ha istruzioni (come il costruttore predefinito) mentre un costruttore senza parametri può contenere istruzioni (come l'inizializzazione di un elenco).
DharmaTurtle

@VinceTino: new()specifica con precisione "deve avere un costruttore pubblico senza parametri"
Flater

162

Questi sono vincoli di tipo generico. Nel tuo caso ce ne sono due:

where T : class

Significa che il tipo Tdeve essere un tipo di riferimento (non un tipo di valore).

where T : new()

Significa che il tipo Tdeve avere un costruttore senza parametri. Avere questo vincolo ti permetterà di fare qualcosa come T field = new T();nel tuo codice che altrimenti non potresti fare.

Quindi combinare i due usando una virgola per ottenere:

where T : class, new()

Buoni punti per il secondo e il terzo, solo per aggiungere informazioni, penso che il secondo punto sia utile quando si fa una riflessione di tipo generico. per esempio. T t = new T (); t.GetType (). GetProperty ("ID"). SetValue (t, uniqueId, null);
Jerry Liang

1
Credo che sia ridondante dire dove T: class, new (), poiché new () implica già la classe perché le strutture non possono avere costruttori predefiniti.
DharmaTurtle

@DharmaTurtle, "le strutture non possono contenere costruttori espliciti senza parametri", non significa che non ne abbiano uno, dice che non puoi definirne uno. fonte: msdn.microsoft.com/tr-tr/library/aa288208(v=vs.71).aspx
Rustem

121

dove T: struct

L'argomento type deve essere un tipo di valore. È possibile specificare qualsiasi tipo di valore tranne Nullable. Vedere Uso dei tipi nullable (Guida per programmatori C #) per ulteriori informazioni.

dove T: classe

L'argomento type deve essere un tipo di riferimento, incluso qualsiasi classe, interfaccia, delegato o tipo di array. (Vedi nota sotto.)

dove T: new () L'argomento type deve avere un costruttore pubblico senza parametri. Se utilizzato insieme ad altri vincoli, il nuovo vincolo () deve essere specificato per ultimo.

dove T: [nome classe base]

L'argomento tipo deve essere o derivare dalla classe base specificata.

dove T: [nome interfaccia]

L'argomento tipo deve essere o implementare l'interfaccia specificata. È possibile specificare più vincoli di interfaccia. L'interfaccia vincolante può anche essere generica.

dove T: U

L'argomento di tipo fornito per T deve essere o derivare dall'argomento fornito per U. Questo è chiamato un vincolo di tipo nudo.


23
Questo è stato utile, ma link alla fonte .
Skean

26

classe newsono 2 vincoli sul parametro di tipo genericoT .
Rispettivamente assicurano:

class

L'argomento type deve essere un tipo di riferimento; questo vale anche per qualsiasi classe, interfaccia, delegato o tipo di array.

new

L'argomento type deve avere un costruttore pubblico senza parametri. Se utilizzato insieme ad altri vincoli, il vincolo new () deve essere specificato per ultimo.

La loro combinazione significa che il tipo Tdeve essere un Tipo di riferimento (non può essere un Tipo valore ) e deve avere un costruttore senza parametri.

Esempio:

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
}

1
Buona dimostrazione. Grazie.
Subhan Ali,

15

new (): Specificare il vincolo new () significa che il tipo T deve usare un costruttore senza parametri, quindi un oggetto può essere istanziato da esso - vedi Costruttori predefiniti .

class: significa che T deve essere un tipo di riferimento, quindi non può essere int, float, double, DateTime o altra struttura (tipo di valore).

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();
    }
}

6

Ciò significa che quel tipo Tdeve essere una classe e avere un costruttore che non accetta alcun argomento.

Ad esempio, devi essere in grado di farlo:

T t = new T();

1
non solo un costruttore, ma un costruttore che non accetta argomenti.
NerdFury,

@NerdFury: grazie. Questo è un po 'importante. Corretto.
Evan Mulawski,

5

dove (Riferimenti per C #)

Il nuovo vincolo () consente al compilatore di sapere che qualsiasi argomento di tipo fornito deve avere un costruttore accessibile senza parametri - o predefinito -

Quindi dovrebbe essere, Tdeve essere una classe e avere un costruttore accessibile senza parametri o predefinito.


4

Ciò che viene dopo "Where" è un vincolo sul tipo generico T che hai dichiarato, quindi:

  • class significa che la T dovrebbe essere una classe e non un tipo di valore o una struttura.

  • new () indica che la classe T dovrebbe avere un costruttore predefinito privo di parametri pubblici definito.


1

Si chiama 'vincolo' sul parametro generico T. Significa che T deve essere un tipo di riferimento (una classe) e che deve avere un costruttore predefinito pubblico.


1

Questo fa parte del meccanismo Generics, in cui la parola chiave where aggiunge vincoli ai tipi che devono essere implementati per poter essere utilizzati come parametri di tipo.


0

quando si utilizza la classe nei vincoli significa che è possibile utilizzare solo il tipo di riferimento, un'altra cosa da aggiungere è quando utilizzare il vincolo new () , deve essere l'ultima cosa che si scrive nei termini Vincoli.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.