C#自身是通过定义两个同名但不同命名空间的类来解决的, 这可能是历史遗留问题导致的.
System.Collections.IList list = new List<int>();
System.Collections.Generic.IList<int> list = new List<int>();
如果我自己有这么个类 Singer<T>, 有一个实例是反射创建的, 要把这个实例赋值给 Singer, 这要怎么处理呢?
var instance = Activator.CreateInstance(...);
// 下面这句怎么写? 这里确实可以通过反射拿到 instance 的具体类型, 但是代码里如何才能赋值给一个 Singer?
// java 里可以用?或者 object 代替, 但是 C#里就直接报错了
Singer<?> singer = instance;
1
hez2010 2022-05-20 22:15:40 +08:00 via Android
不是的,C# 里面非泛型的集合类接口和类型是已经淘汰的类型,一般不会使用。
|
2
zgcwkj 2022-05-22 14:44:47 +08:00
不知道我理解对不对,可以试试 CopyTo 或者 Linq 赋值
|
3
INCerry 2022-05-22 20:45:08 +08:00
如果我理解没错,那你直接强转就可以了呀
```C# var obj = Activator.CreateInstance(typeof(List<int>)); List<int> intList = (List<int>)obj; Console.WriteLine(intList.Count); `` |
4
bthulu OP @INCerry 强转你得知道确切的类型啊,我都知道确切的类型了, 我还反射创建实例干嘛,我直接 new 不好么?
问题就出在这个类型事先是不知道的,是通过 json 配置文件里的注册信息匹配到类的 Type ,你仅仅知道类的 Type , 这个 type 也是通过 Assemble 遍历所有的类,将其中实现了某个接口的类的类型注册到注册器中。就像下面这样, 你怎么个强转法? ``` static Dictionary<string, Type> registers = new(); Type type = registers["key"]; var obj = Activator.CreateInstance(type); ``` |
5
INCerry 2022-05-23 11:42:18 +08:00
@bthulu 那你题目里面的例子举的不是很好,简单的方案你可以直接用 dynamic 或者上面你提到的直接用 IList 。复杂的方案代码生成(表达式树、Emit )
``` var obj = Activator.CreateInstance(typeof(List<int>)); dynamic intList = obj; Console.WriteLine(intList.Count); intList.Add(1); Console.WriteLine(intList[0]); // output : // 0 // 1 ``` |
7
SMGdcAt4kPPQ 2022-05-23 12:23:28 +08:00 via Android 1
让 Singer<T>继承 Singer 即可
|
8
forgottencoast 2022-06-02 22:47:13 +08:00
@ComputerIdiot
一般都是这样处理,也符合 OO 。 |
9
Aloento 2022-07-22 20:42:41 +08:00
@ComputerIdiot 赞同
|
10
bthulu OP @Aloento 继承不行的. Singer<T>里可以定义方法 Add(T t), Singer 里可就没法这样定义了.
Singer<T>继承 Singer, 将 Singer<T>实例赋值给 Singer, 那就没法调用 Add 方法了, 只能转换成 dynamic 去调了 |
11
Aloento 2022-07-24 01:17:18 +08:00
那只能考虑一下 dynamic 了,还好,dynamic 只是初次调用的时间稍微长一点点,再次调用就没什么区别
|
12
hez2010 2022-08-07 23:57:58 +08:00 via Android
interface ISinger
{ void Add(object t); } interface ISinger<T> : ISinger { void Add(T t); } class Singer<T> : ISinger<T> { public void Add(T t) { ... } // 这里显式实现接口确保该方法不会直接公开暴露在 Singer<T> 的成员中 void ISinger.Add(object t) { Add((T)t); } } 试试这样呢? |