簡體   English   中英

未知類型的泛型

[英]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派生的SettingOfInt32SettingOfString

假設您希望能夠將類型為SettingOfInt32SettingOfString對象放入字段中,那么該字段必須具有哪種類型? 當然,這兩種類型都通用,例如object 現在您可能已經意識到,如果要調用SettingOfInt32SettingOfString中都存在的任何方法,則應將該方法移至一個公共基類,例如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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM