Was bedeutet "wo T: Klasse, neu ()"?

Antworten:

329

Dies ist eine Einschränkung für den generischen Parameter T. Es muss ein class(Referenztyp) sein und einen öffentlichen parameterlosen Standardkonstruktor haben.

Das bedeutet Tnicht sein kann int, float, double, DateTimeoder jede andere struct(value - Typ).

Es kann sich um einen stringoder einen anderen benutzerdefinierten Referenztyp handeln, sofern er einen Standardkonstruktor oder einen parameterlosen Konstruktor hat.

NerdFury
quelle
5
Nur um zu verdeutlichen, wenn Sie die Klassenklausel nicht als Teil von where T ... haben, ist es sicher, int, float, double usw. zu verwenden.
AboutDev
1
@AboutDev richtig, Sie müssen Ihren generischen Typparameter nicht einschränken. Wenn Sie jedoch ein Generikum erstellen, das nur für Referenz- oder Werttypen verwendet werden soll, sollten Sie dies angeben. Ohne Einschränkung können Sie Referenztypen (Klassen) oder Werttypen (Strukturen (int, float, double ...)) erwarten.
NerdFury
1
Was ist mit wo T: [Name der Schnittstelle], new ()? Benötigen Sie noch einen parameterlosen Konstruktor?
Vince Tino
3
Um Justins Kommentar zu verdeutlichen, hat ein leerer Konstruktor keine Anweisungen (wie der Standardkonstruktor), während ein parameterloser Konstruktor Anweisungen enthalten kann (wie das Initialisieren einer Liste).
DharmaTurtle
@VinceTino: new()spezifiziert genau "muss einen öffentlichen parameterlosen Konstruktor haben"
Flater
162

Dies sind generische Typeinschränkungen. In Ihrem Fall gibt es zwei davon:

where T : class

Bedeutet, dass der Typ Tein Referenztyp sein muss (kein Werttyp).

where T : new()

Bedeutet, dass der Typ Teinen parameterlosen Konstruktor haben muss. Mit dieser Einschränkung können Sie so etwas wie T field = new T();in Ihrem Code tun, was Sie sonst nicht tun könnten.

Sie kombinieren die beiden dann mit einem Komma, um Folgendes zu erhalten:

where T : class, new()
Justin Niessner
quelle
Gute Punkte für den zweiten und dritten, nur um Informationen hinzuzufügen. Ich denke, der zweite Punkt ist nützlich, wenn Sie in generischer Form reflektieren. z.B. T t = neues T (); t.GetType (). GetProperty ("ID"). SetValue (t, uniqueId, null);
Jerry Liang
1
Ich glaube, es ist überflüssig zu sagen, wo T: class, new (), da new () bereits class impliziert, weil Strukturen keine Standardkonstruktoren haben können.
DharmaTurtle
@DharmaTurtle, "Strukturen dürfen keine expliziten parameterlosen Konstruktoren enthalten", bedeutet nicht, dass sie keine haben, sondern dass Sie keine definieren können. Quelle: msdn.microsoft.com/tr-tr/library/aa288208(v=vs.71).aspx
rustem
121

wo T: struct

Das Typargument muss ein Werttyp sein. Jeder Werttyp außer Nullable kann angegeben werden. Weitere Informationen finden Sie unter Verwenden nullbarer Typen (C # -Programmierhandbuch).

wo T: Klasse

Das Typargument muss ein Referenztyp sein, einschließlich aller Klassen-, Schnittstellen-, Delegaten- oder Arraytypen. (Siehe Anmerkung unten.)

Dabei ist T: new () Das Argument type muss einen öffentlichen parameterlosen Konstruktor haben. In Verbindung mit anderen Einschränkungen muss die neue () Einschränkung zuletzt angegeben werden.

wobei T: [Name der Basisklasse]

Das Typargument muss von der angegebenen Basisklasse sein oder von dieser abgeleitet sein.

wo T: [Schnittstellenname]

Das Typargument muss die angegebene Schnittstelle sein oder diese implementieren. Es können mehrere Schnittstellenbeschränkungen angegeben werden. Die einschränkende Schnittstelle kann auch generisch sein.

wo T: U.

Das für T angegebene Typargument muss das für U angegebene Argument sein oder von diesem abgeleitet sein. Dies wird als nackte Typbeschränkung bezeichnet.

Mohammed Jubayer
quelle
23
Dies war nützlich, aber Link zur Quelle .
Skean
26

class& newsind zwei Einschränkungen für den generischen TypparameterT .
Sie stellen jeweils sicher:

class

Das Typargument muss ein Referenztyp sein. Dies gilt auch für alle Klassen, Schnittstellen, Delegaten oder Array-Typen.

new

Das Typargument muss einen öffentlichen parameterlosen Konstruktor haben. Bei Verwendung zusammen mit anderen Einschränkungen muss die neue () Einschränkung zuletzt angegeben werden.

Ihre Kombination bedeutet, dass der Typ Tein Referenztyp sein muss (kann kein Werttyp sein ) und einen parameterlosen Konstruktor haben muss.

Beispiel:

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
quelle
1
Gute Demonstration. Vielen Dank.
Subhan Ali
15

new (): Wenn Sie die Einschränkung new () angeben, muss Typ T einen parameterlosen Konstruktor verwenden, damit ein Objekt daraus instanziiert werden kann - siehe Standardkonstruktoren .

Klasse: Bedeutet, dass T ein Referenztyp sein muss, damit es sich nicht um eine int-, float-, double-, DateTime- oder andere Struktur (Werttyp) handeln kann.

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
quelle
6

Das bedeutet, dass type Teine Klasse sein und einen Konstruktor haben muss, der keine Argumente akzeptiert.

Zum Beispiel müssen Sie dazu in der Lage sein:

T t = new T();
Evan Mulawski
quelle
1
nicht nur ein Konstruktor, sondern ein Konstruktor, der keine Argumente akzeptiert.
NerdFury
@ NerdFury: Danke. Das ist ein wichtiges Stück. Korrigiert.
Evan Mulawski
5

wo (C # Referenz)

Die new () - Einschränkung informiert den Compiler darüber, dass jedes angegebene Typargument einen zugänglichen parameterlosen oder standardmäßigen Konstruktor haben muss

So sollte es sein, Tmuss eine Klasse sein und einen zugänglichen parameterlosen - oder Standardkonstruktor haben.

Fredrik Widerberg
quelle
4

Was nach dem "Wo" kommt, ist eine Einschränkung für den von Ihnen deklarierten generischen Typ T, also:

  • Klasse bedeutet, dass das T eine Klasse und kein Werttyp oder eine Struktur sein sollte.

  • new () gibt an, dass für die T-Klasse ein öffentlicher parameterfreier Standardkonstruktor definiert sein sollte.

Otman IGHOULASSEN
quelle
1

Es wird als 'Einschränkung' für den generischen Parameter T bezeichnet. Dies bedeutet, dass T ein Referenztyp (eine Klasse) sein und einen öffentlichen Standardkonstruktor haben muss.


quelle
1

Dies ist Teil des Generics-Mechanismus, bei dem das Schlüsselwort where Einschränkungen hinzufügt, welche Typen implementiert werden müssen, um als Typparameter verwendet zu werden.

Peter Lillevold
quelle
0

Wenn Sie die Klasse in Einschränkungen verwenden, bedeutet dies, dass Sie nur den Referenztyp verwenden können. Eine weitere Sache, die Sie hinzufügen müssen, ist, wann Sie die Einschränkung new () verwenden müssen. Dies muss das letzte sein, was Sie in die Constraints-Begriffe schreiben.

Rebwar
quelle