Réponses:
C'est une contrainte sur le paramètre générique T
. Il doit être un class
(type de référence) et doit avoir un constructeur par défaut public sans paramètre.
Cela veut dire T
ne peut pas être un int
, float
, double
, DateTime
ou tout autre struct
(type de valeur).
Il peut s'agir d'un string
ou de tout autre type de référence personnalisé, tant qu'il possède un constructeur par défaut ou sans paramètre.
new()
précise précisément "doit avoir un constructeur public sans paramètre"
Ce sont des contraintes de type génériques. Dans votre cas, il y en a deux:
where T : class
Signifie que le type T
doit être un type de référence (pas un type de valeur).
where T : new()
Signifie que le type T
doit avoir un constructeur sans paramètre. Avoir cette contrainte vous permettra de faire quelque chose comme T field = new T();
dans votre code que vous ne pourriez pas faire autrement.
Vous combinez ensuite les deux à l'aide d'une virgule pour obtenir:
where T : class, new()
où T: struct
L'argument type doit être un type valeur. Tout type de valeur, à l'exception de Nullable, peut être spécifié. Voir Utilisation de types Nullable (Guide de programmation C #) pour plus d'informations.
où T: classe
L'argument type doit être un type de référence, comprenant tout type de classe, d'interface, de délégué ou de tableau. (Voir note ci-dessous.)
où T: new () L'argument type doit avoir un constructeur public sans paramètre. Lorsqu'elle est utilisée conjointement avec d'autres contraintes, la nouvelle contrainte () doit être spécifiée en dernier.
où T: [nom de la classe de base]
L'argument type doit être ou dériver de la classe de base spécifiée.
où T: [nom de l'interface]
L'argument type doit être ou implémenter l'interface spécifiée. Plusieurs contraintes d'interface peuvent être spécifiées. L'interface contraignante peut également être générique.
où T: U
L'argument de type fourni pour T doit être ou dériver de l'argument fourni pour U. Cela s'appelle une contrainte de type nu.
class
& new
sont 2 contraintes sur le paramètre de type génériqueT
.
Respectivement, ils assurent:
class
L'argument type doit être un type de référence; cela s'applique également à tout type de classe, d'interface, de délégué ou de tableau.
new
L'argument type doit avoir un constructeur public sans paramètre. Lorsqu'elle est utilisée avec d'autres contraintes, la nouvelle contrainte () doit être spécifiée en dernier.
Leur combinaison signifie que le type T
doit être un type de référence (ne peut pas être un type de valeur ) et doit avoir un constructeur sans paramètre.
Exemple:
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 (): La spécification de la contrainte new () signifie que le type T doit utiliser un constructeur sans paramètre, afin qu'un objet puisse en être instancié - voir Constructeurs par défaut .
classe: signifie que T doit être un type de référence, il ne peut donc pas être un entier, flottant, double, DateTime ou autre struct (type de valeur).
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();
}
}
Cela signifie que ce type T
doit être une classe et avoir un constructeur qui ne prend aucun argument.
Par exemple, vous devez pouvoir faire ceci:
T t = new T();
La nouvelle contrainte () permet au compilateur de savoir que tout argument de type fourni doit avoir un constructeur accessible sans paramètre - ou par défaut -
Il devrait donc être, T
doit être une classe et avoir un constructeur accessible sans paramètre - ou par défaut.
Ce qui vient après le "Où" est une contrainte sur le type générique T que vous avez déclaré, donc:
classe signifie que le T doit être une classe et non un type de valeur ou une structure.
new () indique que la classe T devrait avoir un constructeur par défaut public sans paramètre défini.
Cela s'appelle une «contrainte» sur le paramètre générique T. Cela signifie que T doit être un type de référence (une classe) et qu'il doit avoir un constructeur public par défaut.
Cela fait partie du mécanisme Generics, où le mot-clé where ajoute des contraintes aux types à implémenter pour être utilisé comme paramètres de type.