Il y a déjà plusieurs bonnes réponses ici, qui expliquent l'avertissement et la raison de celui-ci. Plusieurs de ceux-ci indiquent quelque chose comme avoir un champ statique dans un type générique généralement une erreur .
J'ai pensé ajouter un exemple de la façon dont cette fonctionnalité peut être utile, c'est-à-dire un cas où la suppression de l'avertissement R # est logique.
Imaginez que vous ayez un ensemble de classes d'entité que vous souhaitez sérialiser, par exemple en Xml. Vous pouvez créer un sérialiseur pour cela en utilisant new XmlSerializerFactory().CreateSerializer(typeof(SomeClass))
, mais vous devrez ensuite créer un sérialiseur distinct pour chaque type. En utilisant des génériques, vous pouvez remplacer cela par ce qui suit, que vous pouvez placer dans une classe générique dont les entités peuvent dériver:
new XmlSerializerFactory().CreateSerializer(typeof(T))
Étant donné que vous ne souhaitez probablement pas générer un nouveau sérialiseur chaque fois que vous devez sérialiser une instance d'un type particulier, vous pouvez ajouter ceci:
public class SerializableEntity<T>
{
// ReSharper disable once StaticMemberInGenericType
private static XmlSerializer _typeSpecificSerializer;
private static XmlSerializer TypeSpecificSerializer
{
get
{
// Only create an instance the first time. In practice,
// that will mean once for each variation of T that is used,
// as each will cause a new class to be created.
if ((_typeSpecificSerializer == null))
{
_typeSpecificSerializer =
new XmlSerializerFactory().CreateSerializer(typeof(T));
}
return _typeSpecificSerializer;
}
}
public virtual string Serialize()
{
// .... prepare for serializing...
// Access _typeSpecificSerializer via the property,
// and call the Serialize method, which depends on
// the specific type T of "this":
TypeSpecificSerializer.Serialize(xmlWriter, this);
}
}
Si cette classe n'était PAS générique, alors chaque instance de la classe utiliserait la même _typeSpecificSerializer
.
Puisqu'il est générique cependant, un ensemble d'instances avec le même type pour T
partagera une seule instance de _typeSpecificSerializer
(qui aura été créée pour ce type spécifique), tandis que les instances avec un type différent pour T
utiliseront différentes instances de _typeSpecificSerializer
.
Un exemple
A condition que les deux classes qui s'étendent SerializableEntity<T>
:
// Note that T is MyFirstEntity
public class MyFirstEntity : SerializableEntity<MyFirstEntity>
{
public string SomeValue { get; set; }
}
// Note that T is OtherEntity
public class OtherEntity : SerializableEntity<OtherEntity >
{
public int OtherValue { get; set; }
}
... utilisons-les:
var firstInst = new MyFirstEntity{ SomeValue = "Foo" };
var secondInst = new MyFirstEntity{ SomeValue = "Bar" };
var thirdInst = new OtherEntity { OtherValue = 123 };
var fourthInst = new OtherEntity { OtherValue = 456 };
var xmlData1 = firstInst.Serialize();
var xmlData2 = secondInst.Serialize();
var xmlData3 = thirdInst.Serialize();
var xmlData4 = fourthInst.Serialize();
Dans ce cas, sous le capot, firstInst
et secondInst
seront des instances de la même classe (à savoir SerializableEntity<MyFirstEntity>
), et en tant que tels, ils partageront une instance de _typeSpecificSerializer
.
thirdInst
et fourthInst
sont des instances d'une classe différente ( SerializableEntity<OtherEntity>
), et partageront donc une instance _typeSpecificSerializer
qui est différente des deux autres.
Cela signifie que vous obtenez différentes instances de sérialiseur pour chacun de vos types d' entités , tout en les gardant statiques dans le contexte de chaque type réel (c'est-à-dire partagées entre les instances d'un type spécifique).