定义了一个泛型类, 有什么办法能将一个泛型类实例赋值给未指定泛型的泛型类吗? 类似 Java 里的 List = new ArrayList<String>()

2022-05-20 15:28:31 +08:00
 bthulu

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;
1479 次点击
所在节点    C#
12 条回复
hez2010
2022-05-20 22:15:40 +08:00
不是的,C# 里面非泛型的集合类接口和类型是已经淘汰的类型,一般不会使用。
zgcwkj
2022-05-22 14:44:47 +08:00
不知道我理解对不对,可以试试 CopyTo 或者 Linq 赋值
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);
``
bthulu
2022-05-23 08:19:08 +08:00
@INCerry 强转你得知道确切的类型啊,我都知道确切的类型了, 我还反射创建实例干嘛,我直接 new 不好么?
问题就出在这个类型事先是不知道的,是通过 json 配置文件里的注册信息匹配到类的 Type ,你仅仅知道类的 Type , 这个 type 也是通过 Assemble 遍历所有的类,将其中实现了某个接口的类的类型注册到注册器中。就像下面这样, 你怎么个强转法?
```
static Dictionary<string, Type> registers = new();

Type type = registers["key"];
var obj = Activator.CreateInstance(type);
```
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
```
INCerry
2022-05-23 11:44:26 +08:00
@INCerry 还有 Roslyn 动态编译,类似 natasha 那样
SMGdcAt4kPPQ
2022-05-23 12:23:28 +08:00
让 Singer<T>继承 Singer 即可
forgottencoast
2022-06-02 22:47:13 +08:00
@ComputerIdiot
一般都是这样处理,也符合 OO 。
Aloento
2022-07-22 20:42:41 +08:00
bthulu
2022-07-23 10:11:06 +08:00
@Aloento 继承不行的. Singer<T>里可以定义方法 Add(T t), Singer 里可就没法这样定义了.
Singer<T>继承 Singer, 将 Singer<T>实例赋值给 Singer, 那就没法调用 Add 方法了, 只能转换成 dynamic 去调了
Aloento
2022-07-24 01:17:18 +08:00
那只能考虑一下 dynamic 了,还好,dynamic 只是初次调用的时间稍微长一点点,再次调用就没什么区别
hez2010
2022-08-07 23:57:58 +08:00
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); }
}

试试这样呢?

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/854196

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX