[英]C# generic factory method
也許這是一個簡單的C#新手問題,但是就這樣吧-與我的其他問題相比,這是一個全新的突破。其他問題是如此的困難,以至於沒人知道答案。 :)
假設我在C#中有一個泛型類型:
Thing<T>
假設我想使用靜態工廠方法制作東西。 在Java中,這沒有問題:
public static <T> Thing<T> createThing()
{
return flag ? new Thing<Integer>(5) : new Thing<String>("hello");
}
如何在C#中執行此操作? 謝謝。
如果要使用許多不同的模板參數之一返回模板化類的實例,則一種實現方法是使用抽象基(或接口):
abstract class UntypedThing { }
class Thing<T> : UntypedThing
{
public Thing(T t) { }
}
class Foo
{
public static UntypedThing createThing(bool flag)
{
if (flag)
return new Thing<int>(5);
else return new Thing<String>("hello");
}
}
UntypedThing
類將包含盡可能多的不依賴模板類型的代碼。 理想情況下, Thing
類將僅包含依賴於模板類型的代碼。 工廠類Foo
始終返回前者。
從理論上講,您可以使用反射來構建正確的泛型類型,但是對於您來說這將是毫無用處的,因為有時您需要將其轉換為不太具體的類型。
public class ThingFactory {
public object Create(bool flag) {
Type outputType = null;
if(flag) {
outputType = typeof(string);
} else {
outputType = typeof(int);
}
return Activator.CreateInstance(typeof(Thing<>).MakeGenericType(outputType));
}
}
如您所見,這樣做的價值大約為零,因為您需要將返回類型強制轉換為所需的類型,這意味着確定返回類型的邏輯必須位於Create
方法之外。
我將使用Reinderien的方法,並且具有非通用基礎。 這是最理智和慣用的方法。
哦,當我只是嘗試做一些簡單的事情時,我就會陷入麻煩。
事實證明, C#4允許這種協方差 。 首先,我必須將Thing用作接口並指定“ out”通用參數:
public interface Thing<out T> {...}
但是,如果我做某些事情,C#將不允許我使用協方差。 例如,如果我嘗試從接口返回T:
public interface Thing<out T>
{
public T GetT();
即使我設法與Thing保持協方差,我該怎么辦?
Thing<object> thing=createThing();
編譯器告訴我,不能從使用情況推斷類型。
假設我說擰整個T東西並使工廠方法返回類型為對象的Thing:
public static Thing<object> createThing() {...}
很好,但是現在放在哪里?
IList<Thing<object>> list=new List<Thing<object>>();
Thing<object> thing=createThing();
list.Add(thing);
是的,我不得不說這是對象類型為T的Thing列表,因為C#沒有通配符類型。
如果這是Java,我會簡單地說:
public class Thing<T> {...}
public static <T> Thing<T> createThing() {...}
List<?> things=new ArrayList<Thing<?>>();
Thing<?> thing=createThing();
things.add(thing);
如果我想通過說T必須是特殊類型來提高安全性,我會說:
public static <T extends MyBaseType> Thing<T> createThing() {...}
List<? extends MyBaseType> things=new ArrayList<Thing<? extends MyBaseType>>();
Thing<? extends MyBaseType> thing=createThing();
things.add(thing);
然后,當我獲得更多信息時,我便想出了T是什么。
這一切似乎都歸結為C#中不完整的泛型協方差以及缺少C#泛型通配符。 (我仍然認為這不是擦除問題。)
那我該怎么辦? 唯一要做的簡單事情似乎是遵循Reinderien的回答並拆分出一個非泛型基類。
(我想知道在這個非泛型基類中是否可以有對象getValue(),然后在子類中使用協方差返回T getValue()?哎呀,我對此感到厭倦了-我將其留給另一個天。)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.