Odpowiedzi:
Jest to ograniczenie parametru ogólnego T
. Musi być class
(typem referencyjnym) i musi mieć publiczny konstruktor domyślny bez parametrów.
To znaczy T
nie może być int
, float
, double
, DateTime
lub dowolny inny struct
(typ wartości).
Może to być string
dowolny niestandardowy typ odwołania, o ile ma on domyślny lub parametryczny konstruktor.
new()
precyzyjnie określa „musi mieć publiczny konstruktor bez parametrów”
Są to ogólne ograniczenia typu. W twoim przypadku są dwa:
where T : class
Oznacza, że typ T
musi być typem odniesienia (a nie typem wartości).
where T : new()
Oznacza, że typ T
musi 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()
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”.
class
& new
są 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 T
musi 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
}
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();
}
}
Oznacza to, że typ T
musi 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();
Ograniczenie new () informuje kompilator, że każdy podany argument typu musi mieć dostępny konstruktor bez parametrów - lub domyślny -
Tak powinno być, T
musi być klasą i mieć dostępny bez parametrów - lub domyślny konstruktor.
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.
Nazywa się to „ograniczeniem” parametru ogólnego T. Oznacza to, że T musi być typem referencyjnym (klasą) i musi mieć publiczny domyślny konstruktor.
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.