[英]Generics of unknown type
我正在創建一個設置類,如下所示:
class Setting<T> {...}
我將所有設置存儲在樹中,如下所示:
class SettingsNode {
public Setting<> setting;
public Setting<> child;
public Setting<> sibling;
}
這顯然由於<>
而無法編譯。 我可以有多種類型( Setting<int>
, Setting<string>
等),所以我不知道如何創建SettingsNode。
所以我將其更改為:
class SettingsNode {
public object setting;
public object child;
public object sibling;
}
但是在轉換為正確的類型時遇到了麻煩:
// Create a setting from a type name as text
SettingsNode tmp = new SettingsNode();
Type genericType = typeof(Setting<>);
Type[] typeArgs = { Type.GetType("System.Int32") };
Type cType = genericType.MakeGenericType(typeArgs);
tmp.setting = Activator.CreateInstance(cType);
// Here's where I have a problem
Type baseType = typeArgs[0];
((Setting<baseType>)(tmp.setting)).SomeFunction();
最后一行的錯誤是:
找不到類型或名稱空間名稱“ baseType”(您是否缺少using指令或程序集引用?)
我怎樣才能做到這一點? 謝謝!
一種選擇是您可以繼續使用dynamic
關鍵字:
class SettingsNode
{
public dynamic setting;
public dynamic child;
public dynamic sibling;
}
所以你可以這樣:
SettingsNode tmp = new SettingsNode();
tmp.setting = new Setting<int>();
tmp.setting.SomeFunction()
無需使用反射
為什么不擁有:
class SettingsNode<T> {
public Setting<T> setting;
public Setting<T> child;
public Setting<T> sibling;
}
如果您真的想走這條路,請創建一個抽象的非通用基類abstract class Setting
和一個通用的Setting<T> : Setting
。 在非通用方法中使用object
而不是T
定義所有通用方法,並使用通用方法作為適配器,該適配器調用super
的方法/屬性並在每個方法/屬性中強制轉換object <=> T。
我認為泛型不是正確的工具。 泛型是編譯時的工具 :如果在編譯時不知道泛型類型,則與非泛型類型相比沒有任何優勢。
因此,除非打算在代碼中顯式使用Setting<Int32>
和Setting<String>
,否則在此處使用泛型是沒有意義的,您最好還是堅持使用Setting
。
泛型無法做到這一點。
泛型的全部要點是在編譯時在類型系統中指定類型參數。
您正在嘗試使這些字段沒有已知的類型。
相反,您應該使泛型類繼承自非泛型SettingsBase
基類(或接口),並創建該類型的字段。
調用代碼可以將它們強制轉換回實際的泛型類型。
如果Setting<T>
定義了一個方法:
public T Transform(T value);
...並且您可以定義一個類型為Setting<?>
的字段,那么Transform
將接受哪種類型的參數? object
是所有可能T
共有的唯一類型。 因此,您將失去所有類型的安全性。 Transform
將返回哪種類型的參數? 同樣, object
,所以您必須強制轉換所有內容。
您應該將每個通用類實例視為不同的類型:手動將Setting<T>
類復制為SettingOfInt32
並將所有T
替換為Int32
,這是通過通用語法Setting<Int32>
自動實現的。 因此,不要認為Setting<Int32>
和Setting<String>
都是Setting<T>
,您應該認為自己具有從Object
派生的SettingOfInt32
和SettingOfString
。
假設您希望能夠將類型為SettingOfInt32
和SettingOfString
對象放入字段中,那么該字段必須具有哪種類型? 當然,這兩種類型都通用,例如object
。 現在您可能已經意識到,如果要調用SettingOfInt32
和SettingOfString
中都存在的任何方法,則應將該方法移至一個公共基類,例如Setting
。 然后,您字段的類型必須為“ Setting
,一切都很好。
public class Setting<T> : Setting { }
public abstract class Setting { }
這也迫使您處理諸如上面的“ Transform
示例之類的事情。 您是否將其包括在通用基類中? 也許吧,也許不是。 您使用什么類型代替T
? 也許是object
,也許是其他。 您是否進行顯式類型檢查? 也許...
如所述,我認為在這種情況下不應該使用泛型。 如果您希望/需要堅持下去,可以嘗試使用具有多個泛型的類。
public class SettingsNode<TSetting, TChild, TSibbling>
{
public Setting<TSetting> Setting { get; set; }
public Setting<TChild> Child { get; set; }
public Setting<TSibbling> Sibling { get; set; }
}
public class Setting<T>
{
public T Value;
}
SettingsNode<String, int, int> node = new SettingsNode<string, int, int>();
node.Sibling = new Setting<int>();
node.Setting = new Setting<string>();
node.Child = new Setting<int>();
當我不知道期望哪種類型時,我采用了另一種方法 。 這涉及到動態關鍵字的使用,因此需要c#4.0+
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.