Co znaczy „gdzie T: klasa, nowa ()”?

Odpowiedzi:

329

Jest to ograniczenie parametru ogólnego T. Musi być class(typem referencyjnym) i musi mieć publiczny konstruktor domyślny bez parametrów.

To znaczy Tnie może być int, float, double, DateTimelub dowolny inny struct(typ wartości).

Może to być stringdowolny niestandardowy typ odwołania, o ile ma on domyślny lub parametryczny konstruktor.

NerdFury
źródło
5
Dla wyjaśnienia, jeśli nie masz klauzuli klasy jako części gdzie T ..., to bezpiecznie jest używać int, float, double itp.
AboutDev
1
@Informacje poprawne, nie musisz nakładać ograniczeń na ogólny parametr typu. Ale jeśli tworzysz ogólny, który oczekuje, że będzie działał tylko na typach referencyjnych lub wartościowych, powinieneś to określić. Bez ograniczeń można oczekiwać typów odwołań (klas) lub typów wartości (struktur (int, float, double ...)).
NerdFury,
1
Co z T: [nazwa interfejsu], new ()? Czy nadal potrzebujesz konstruktora bez parametrów?
Vince Tino,
3
Aby wyjaśnić komentarz Justina, pusty konstruktor nie ma instrukcji (jak konstruktor domyślny), podczas gdy konstruktor bez parametrów może zawierać instrukcje (jak inicjowanie listy).
DharmaTurtle
@VinceTino: new()precyzyjnie określa „musi mieć publiczny konstruktor bez parametrów”
Flater
162

Są to ogólne ograniczenia typu. W twoim przypadku są dwa:

where T : class

Oznacza, że ​​typ Tmusi być typem odniesienia (a nie typem wartości).

where T : new()

Oznacza, że ​​typ Tmusi mieć konstruktor bez parametrów. Posiadanie tego ograniczenia pozwoli ci zrobić coś takiego jak T field = new T();w kodzie, czego inaczej nie będziesz w stanie zrobić.

Następnie połącz je za pomocą przecinka, aby uzyskać:

where T : class, new()
Justin Niessner
źródło
Dobre punkty za drugi i trzeci, tylko dla dodania informacji, myślę, że drugi punkt jest przydatny przy odbiciu w typie ogólnym. na przykład. T t = nowy T (); t.GetType (). GetProperty („ID”). SetValue (t, uniqueId, null);
Jerry Liang
1
Uważam, że nie ma sensu mówić, gdzie T: klasa, nowa (), ponieważ new () już implikuje klasę, ponieważ struktury nie mogą mieć domyślnych konstruktorów.
DharmaTurtle
@DharmaTurtle, „struktury nie mogą zawierać jawnych konstruktorów bez parametrów”, nie oznacza, że ​​nie mają jednego, mówi, że nie można go zdefiniować. źródło: msdn.microsoft.com/tr-tr/library/aa288208(v=vs.71).aspx
rustem
121

gdzie T: struct

Argument typu musi być typem wartości. Można określić dowolny typ wartości oprócz Nullable. Aby uzyskać więcej informacji, zobacz Korzystanie z typów dopuszczających wartości zerowe (Podręcznik programowania w języku C #).

gdzie T: klasa

Argument typu musi być typem referencyjnym, w tym dowolną klasą, interfejsem, delegatem lub tablicą. (Patrz przypis poniżej.)

gdzie T: new () Argument typu musi mieć publiczny konstruktor bez parametrów. W przypadku użycia w połączeniu z innymi ograniczeniami nowe () ograniczenie musi zostać określone na końcu.

gdzie T: [nazwa klasy podstawowej]

Argument typu musi pochodzić lub pochodzić z określonej klasy bazowej.

gdzie T: [nazwa interfejsu]

Argumentem typu musi być lub implementować określony interfejs. Można określić wiele ograniczeń interfejsu. Interfejs ograniczający może być również ogólny.

gdzie T: U

Argument typu dostarczony dla T musi pochodzić lub pochodzić z argumentu dostarczonego dla U. Nazywa się to ograniczeniem typu „goły”.

Mohammed Jubayer
źródło
23
Było to przydatne, ale link do źródła .
Skean
26

class& newsą 2 ograniczenia ogólnego parametru parametruT .
Odpowiednio zapewniają one:

class

Argument typu musi być typem referencyjnym; dotyczy to także dowolnej klasy, interfejsu, delegata lub typu tablicy.

new

Argument typu musi mieć publiczny konstruktor bez parametrów. W połączeniu z innymi ograniczeniami nowe () ograniczenie musi zostać określone na końcu.

Ich kombinacja oznacza, że ​​typ Tmusi być typem odniesienia (nie może być typem wartości ) i musi mieć konstruktor bez parametrów.

Przykład:

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
źródło
1
Dobra demonstracja. Dzięki.
Subhan Ali,
15

new (): Określenie ograniczenia new () oznacza, że ​​typ T musi używać konstruktora bez parametrów, aby obiekt mógł być z niego utworzony - patrz Konstruktory domyślne .

klasa: Oznacza, że ​​T musi być typem referencyjnym, więc nie może być liczbą całkowitą, zmiennoprzecinkową, podwójną, DateTime ani inną strukturą (typem wartości).

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
źródło
6

Oznacza to, że typ Tmusi być klasą i mieć konstruktor, który nie przyjmuje żadnych argumentów.

Na przykład musisz być w stanie to zrobić:

T t = new T();
Evan Mulawski
źródło
1
nie tylko konstruktor, ale konstruktor, który nie przyjmuje żadnych argumentów.
NerdFury
@NerdFury: Dzięki. To ważny kawałek. Poprawione
Evan Mulawski,
5

gdzie (C # Odniesienie)

Ograniczenie new () informuje kompilator, że każdy podany argument typu musi mieć dostępny konstruktor bez parametrów - lub domyślny -

Tak powinno być, Tmusi być klasą i mieć dostępny bez parametrów - lub domyślny konstruktor.

Fredrik Widerberg
źródło
4

To, co następuje po „Where”, jest ograniczeniem zadeklarowanego przez ciebie typu ogólnego T, więc:

  • klasa oznacza, że ​​T powinna być klasą, a nie typem wartości lub strukturą.

  • new () wskazuje, że klasa T powinna mieć zdefiniowany konstruktor domyślny wolny od parametrów publicznych.

Otman IGHOULASSEN
źródło
1

Nazywa się to „ograniczeniem” parametru ogólnego T. Oznacza to, że T musi być typem referencyjnym (klasą) i musi mieć publiczny domyślny konstruktor.


źródło
1

Jest to część mechanizmu Generics, w którym słowo kluczowe dodaje ograniczenia do tego, jakie typy muszą zostać zaimplementowane, aby mogły zostać użyte jako parametry typu.

Peter Lillevold
źródło
0

kiedy używasz klasy w ograniczeniach, oznacza to, że możesz używać tylko typu Referencyjnego, kolejną rzeczą do dodania jest to, kiedy używasz ograniczenia new () , musi to być ostatnia rzecz, którą piszesz w warunkach Ograniczeń.

Rebwar
źródło