Jest już kilka dobrych odpowiedzi, które wyjaśniają ostrzeżenie i jego przyczynę. Kilka z nich stwierdza coś w rodzaju błędu statycznego w typie ogólnym, generalnie błąd .
Pomyślałem, że dodam przykład, w jaki sposób ta funkcja może być użyteczna, tj. Przypadek, w którym tłumienie ostrzeżenia R # ma sens.
Wyobraź sobie, że masz zestaw klas jednostek, które chcesz serializować, powiedz Xml. Możesz utworzyć do tego celu serializator new XmlSerializerFactory().CreateSerializer(typeof(SomeClass))
, ale wtedy będziesz musiał utworzyć osobny serializator dla każdego typu. Używając ogólnych, możesz zamienić to na następujące, które możesz umieścić w ogólnej klasie, z której jednostki mogą pochodzić:
new XmlSerializerFactory().CreateSerializer(typeof(T))
Ponieważ prawdopodobnie nie chcesz generować nowego serializatora za każdym razem, gdy musisz serializować wystąpienie określonego typu, możesz dodać to:
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);
}
}
Jeśli ta klasa NIE byłaby ogólna, wówczas każda instancja klasy użyłaby tego samego _typeSpecificSerializer
.
Ponieważ jest to jednak rodzaj ogólny, zestaw instancji tego samego typu dla T
będzie współużytkować pojedyncze wystąpienie _typeSpecificSerializer
(które zostanie utworzone dla tego określonego typu), podczas gdy wystąpienia o innym typie dla T
będą używać różnych wystąpień _typeSpecificSerializer
.
Przykład
Pod warunkiem, że dwie klasy, które rozszerzają 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; }
}
... użyjmy ich:
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();
W tym przypadku, w obszarze okapu, firstInst
i secondInst
będzie instancje tej samej klasy (tj SerializableEntity<MyFirstEntity>
), i jako takie, będą dzielić wystąpienie _typeSpecificSerializer
.
thirdInst
i fourthInst
przypadki, w innej klasy ( SerializableEntity<OtherEntity>
), a więc będą dzielić instancję _typeSpecificSerializer
to różni się od pozostałych dwóch.
Oznacza to, że otrzymujesz różne instancje serializatora dla każdego z typów jednostek , jednocześnie zachowując je statycznie w kontekście każdego rzeczywistego typu (tj. Współużytkowane przez instancje określonego typu).