มีคำตอบที่ดีอยู่แล้วหลายข้อที่อธิบายคำเตือนและเหตุผลของมัน หลายเหล่านี้บางสิ่งบางรัฐเช่นมีข้อมูลการคงที่ในประเภททั่วไปโดยทั่วไปความผิดพลาด
ฉันคิดว่าฉันจะเพิ่มตัวอย่างว่าคุณลักษณะนี้มีประโยชน์อย่างไรเช่นกรณีที่การระงับ R # - การรับรู้ทำให้เข้าใจได้
ลองนึกภาพคุณมีชุดของคลาสเอนทิตีที่คุณต้องการทำให้เป็นอนุกรมพูดกับ Xml คุณสามารถสร้าง serializer สำหรับการใช้นี้new XmlSerializerFactory().CreateSerializer(typeof(SomeClass))
แต่แล้วคุณจะต้องสร้าง serializer แยกต่างหากสำหรับแต่ละประเภท ใช้ generics คุณสามารถแทนที่ด้วยสิ่งต่อไปนี้ซึ่งคุณสามารถวางในคลาสทั่วไปที่เอนทิตีสามารถสืบทอดมาจาก:
new XmlSerializerFactory().CreateSerializer(typeof(T))
เนื่องจากคุณอาจไม่ต้องการสร้าง serializer ใหม่ทุกครั้งที่คุณต้องการทำให้เป็นอินสแตนซ์ของประเภทเฉพาะคุณอาจเพิ่มสิ่งนี้:
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);
}
}
_typeSpecificSerializer
ถ้าชั้นนี้ไม่ได้ทั่วไปแล้วตัวอย่างของการเรียนในแต่ละจะใช้เหมือนกัน
เพราะมันเป็นเรื่องทั่วไป แต่ชุดของอินสแตนซ์ชนิดเดียวกันสำหรับการT
จะมีส่วนร่วมเช่นเดียวของ_typeSpecificSerializer
(ซึ่งจะได้รับการสร้างขึ้นสำหรับประเภทที่เฉพาะเจาะจงที่) ในขณะที่กรณีที่มีประเภทที่แตกต่างกันสำหรับการจะใช้อินสแตนซ์ที่แตกต่างกันของT
_typeSpecificSerializer
ตัวอย่าง
ให้ทั้งสองคลาสที่ขยาย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; }
}
... ลองใช้มัน:
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();
ในกรณีนี้ภายใต้ประทุน, firstInst
และsecondInst
จะเป็นกรณีของชั้นเดียวกัน (คือSerializableEntity<MyFirstEntity>
) _typeSpecificSerializer
และเป็นเช่นพวกเขาจะแบ่งปันตัวอย่างของ
thirdInst
และfourthInst
เป็นอินสแตนซ์ของคลาสที่แตกต่าง ( SerializableEntity<OtherEntity>
) และจะแชร์อินสแตนซ์_typeSpecificSerializer
ที่แตกต่างจากอีกสองรายการ
ซึ่งหมายความว่าคุณจะได้รับ serializer-instance ที่แตกต่างกันสำหรับแต่ละประเภทเอนทิตีของคุณในขณะที่ยังคงรักษาพวกเขาไว้ในบริบทของแต่ละประเภทจริง (เช่นแบ่งปันระหว่างอินสแตนซ์ที่เป็นประเภทเฉพาะ)