我正在创建一个类似的设置类:
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指令或程序集引用?)
我该怎么做?谢谢!
答案 0 :(得分:2)
一种选择是您可以继续使用dynamic
关键字:
class SettingsNode
{
public dynamic setting;
public dynamic child;
public dynamic sibling;
}
所以你可以这样做:
SettingsNode tmp = new SettingsNode();
tmp.setting = new Setting<int>();
tmp.setting.SomeFunction()
无需使用反射
答案 1 :(得分:2)
为什么没有:
class SettingsNode<T> {
public Setting<T> setting;
public Setting<T> child;
public Setting<T> sibling;
}
答案 2 :(得分:1)
如果你真的想要沿着这条路线走下去,那就制作一个抽象的非通用基类abstract class Setting
和一个通用的Setting<T> : Setting
。使用object
而不是T
定义非泛型方法中的所有常用方法,并使用泛型方法作为调用super
的方法/属性的适配器并执行转换对象&lt; = &gt;每个方法/属性中的T.
答案 3 :(得分:0)
我不认为仿制药是正确的工具。泛型是编译时工具:如果在编译时不知道泛型类型,则没有优于非泛型类型的优势。
因此,除非您计划明确地在代码中使用Setting<Int32>
和Setting<String>
,否则在此处使用泛型毫无意义,您也可以坚持使用Setting
。
答案 4 :(得分:0)
泛型不能这样做。
泛型的全部意义是在类型系统中指定类型参数 - 在编译时
你试图让这些字段没有已知类型。
相反,您应该使泛型类继承自非泛型SettingsBase
基类(或接口),并创建该类型的字段。
调用代码可以将它们转换回实际的泛型类型。
答案 5 :(得分:0)
如果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>
,而不是SettingOfInt32
和SettingOfString
都是Object
。 }。
想象一下,您希望能够将SettingOfInt32
和SettingOfString
类型的对象放在一个字段中,该字段必须具有哪种类型?当然,这两种类型都是共同的类型,例如object
。现在您可能会意识到,如果要调用SettingOfInt32
和SettingOfString
中存在的任何方法,则应将该方法移动到公共基类,例如: Setting
。那么你的字段类型必须是Setting
,一切都很好。
public class Setting<T> : Setting { }
public abstract class Setting { }
这也迫使您处理上述Transform
示例之类的事情。你把它包含在公共基类中吗?也许,也许不是。您使用什么类型而不是T
?也许是object
,也许还有别的。你做了明确的类型检查吗?可能...
答案 6 :(得分:0)
如上所述,我不认为应该在这种情况下使用泛型。 如果你想/需要坚持下去,你可以尝试使用具有多个泛型的类。
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>();
Here's a different approach 当我不知道期待什么类型时,我服用了一次。这涉及到动态关键字的使用,因此需要c#4.0 +