ฉันพบปัญหานี้ในกรณีที่ง่ายกว่าในการต้องการวิธีการคงที่ทั่วไปที่สามารถใช้อะไรก็ได้ "nullable" (ไม่ว่าจะเป็นประเภทอ้างอิงหรือ Nullables) ซึ่งทำให้ฉันมาถึงคำถามนี้โดยไม่มีวิธีแก้ปัญหาที่น่าพอใจ ดังนั้นฉันจึงคิดวิธีแก้ปัญหาของตัวเองซึ่งค่อนข้างง่ายในการแก้ปัญหามากกว่าคำถามที่ระบุไว้ของ OP โดยมีเพียงสองวิธีที่มากเกินไปวิธีหนึ่งที่ใช้ a T
และมีข้อ จำกัดwhere T : class
และอีกวิธีหนึ่งที่ใช้T?
และมีwhere T : struct
และมีความ
จากนั้นฉันก็รู้ว่าโซลูชันนั้นสามารถใช้กับปัญหานี้เพื่อสร้างโซลูชันที่ตรวจสอบได้ในเวลาคอมไพล์โดยทำให้ตัวสร้างเป็นแบบส่วนตัว (หรือได้รับการป้องกัน) และใช้วิธีการโรงงานแบบคงที่:
//this class is to avoid having to supply generic type arguments
//to the static factory call (see CA1000)
public static class Foo
{
public static Foo<TFoo> Create<TFoo>(TFoo value)
where TFoo : class
{
return Foo<TFoo>.Create(value);
}
public static Foo<TFoo?> Create<TFoo>(TFoo? value)
where TFoo : struct
{
return Foo<TFoo?>.Create(value);
}
}
public class Foo<T>
{
private T item;
private Foo(T value)
{
item = value;
}
public bool IsNull()
{
return item == null;
}
internal static Foo<TFoo> Create<TFoo>(TFoo value)
where TFoo : class
{
return new Foo<TFoo>(value);
}
internal static Foo<TFoo?> Create<TFoo>(TFoo? value)
where TFoo : struct
{
return new Foo<TFoo?>(value);
}
}
ตอนนี้เราสามารถใช้มันได้ดังนี้:
var foo1 = new Foo<int>(1); //does not compile
var foo2 = Foo.Create(2); //does not compile
var foo3 = Foo.Create(""); //compiles
var foo4 = Foo.Create(new object()); //compiles
var foo5 = Foo.Create((int?)5); //compiles
หากคุณต้องการตัวสร้างแบบไม่มีพารามิเตอร์คุณจะไม่ได้รับความสวยงามจากการโอเวอร์โหลด แต่คุณยังสามารถทำสิ่งนี้ได้:
public static class Foo
{
public static Foo<TFoo> Create<TFoo>()
where TFoo : class
{
return Foo<TFoo>.Create<TFoo>();
}
public static Foo<TFoo?> CreateNullable<TFoo>()
where TFoo : struct
{
return Foo<TFoo?>.CreateNullable<TFoo>();
}
}
public class Foo<T>
{
private T item;
private Foo()
{
}
public bool IsNull()
{
return item == null;
}
internal static Foo<TFoo> Create<TFoo>()
where TFoo : class
{
return new Foo<TFoo>();
}
internal static Foo<TFoo?> CreateNullable<TFoo>()
where TFoo : struct
{
return new Foo<TFoo?>();
}
}
และใช้มันดังนี้:
var foo1 = new Foo<int>(); //does not compile
var foo2 = Foo.Create<int>(); //does not compile
var foo3 = Foo.Create<string>(); //compiles
var foo4 = Foo.Create<object>(); //compiles
var foo5 = Foo.CreateNullable<int>(); //compiles
วิธีแก้ปัญหานี้มีข้อเสียเล็กน้อยอย่างหนึ่งคือคุณอาจต้องการใช้ 'ใหม่' ในการสร้างวัตถุ ก็คือว่าคุณจะไม่สามารถที่จะใช้Foo<T>
เป็นอาร์กิวเมนต์ประเภททั่วไปสำหรับข้อ จำกัด where TFoo: new()
ประเภทของสิ่งที่ชอบ: สุดท้ายคือบิตของรหัสพิเศษที่คุณต้องการที่นี่ซึ่งจะเพิ่มขึ้นโดยเฉพาะอย่างยิ่งหากคุณต้องการตัวสร้างที่โอเวอร์โหลดหลายตัว