C# 泛型的协方差/转换问题
以代码为例:C# 泛型的协方差/转换问题,c#,generics,C#,Generics,以代码为例: using System.Collections.Generic; namespace TestingTypes { class Program { static void Main(string[] args) { var strings = new List<string>(); INeedToPassThisMethodAListOfObj
using System.Collections.Generic;
namespace TestingTypes
{
class Program
{
static void Main(string[] args)
{
var strings = new List<string>();
INeedToPassThisMethodAListOfObjects(strings as List<object>);
}
static void INeedToPassThisMethodAListOfObjects(List<object> objects) { }
}
}
1>------ Build started: Project: TestingTypes, Configuration: Debug Any CPU ------
1>c:\users\[censored]\TestingTypes\Program.cs(9,41,9,64): error CS0039: Cannot convert
type 'System.Collections.Generic.List<string>' to
'System.Collections.Generic.List<object>' via a reference conversion, boxing
conversion, unboxing conversion, wrapping conversion, or null type conversion
使用System.Collections.Generic;
命名空间测试类型
{
班级计划
{
静态void Main(字符串[]参数)
{
var strings=新列表();
INEEDTopassThisMethodAlistOfObject(字符串作为列表);
}
静态无效IneedToPassThisMethodAlistOfObject(列表对象){}
}
}
1> ----构建已启动:项目:测试类型,配置:调试任何CPU------
1> c:\users\[censtered]\TestingTypes\Program.cs(9,41,9,64):错误CS0039:无法转换
键入“System.Collections.Generic.List”以
“System.Collections.Generic.List”通过引用转换、装箱
转换、取消装箱转换、换行转换或空类型转换
你可以说列表就是一个列表,因为字符串是一个对象,而C#4应该支持泛型类型中的协方差
- 为什么编译器说它不能转换类型
- 如何将“字符串”传递给该方法
列表
不是列表
您可以在list
上调用list.Add(new TextBox())
,但显然,相同的调用在list
上不起作用
C#泛型只允许在泛型类型不可变的情况下使用协方差(这是从列表到IEnumerable工作的转换)
如果需要将列表传递给方法,可以尝试传递
listOfStrings.Cast<object>();
listofstring.Cast();
另一方面,如果使用该解决方案,对方法调用中的列表所做的任何修改都不会反映在原始列表中(因为对Cast
的调用会创建一个新列表)
如果您控制了INeedToPassThisMethodAListOfObjects方法
,并且该方法只需在集合上迭代,而不需要修改它,您可以将参数类型更改为IEnumerable
,在这种情况下,您只需传递列表
,而不会出现任何问题。您必须将字符串转换为对象。有一个很好的LINQ方法可以做到这一点
var strings = new List<string>();
INeedToPassThisMethodAListOfObjects(strings.Cast<object>());
var strings=newlist();
IneedToPassThisMethodAlistOfObject(strings.Cast());
编辑
根据你自己的链接
在C#中,在以下场景中支持方差:
- 阵列中的协方差(自C#1.0起)
- 代表中的协方差和逆变换,也称为“方法组方差”(自C#2.0起)
- 接口和委托中泛型类型参数的差异(自C#4.0以来)
因此IEnumerable将接受列表接口可以是变量;类不能
如果将字符串
集合传递为uncasted并将声明更改为
static void INeedToPassThisMethodAListOfObjects(IEnumerable<object> objects) { }
static void inedtopassthis方法论对象(IEnumerable对象){
但是,这取决于您是否需要此函数中的列表。是的,它有点像:@BarryFandango-实际上不是。注意这篇文章。列表是一个IEnumerable。这是因为IEnumerable对象是不可变的(正如我在回答中所说的),我真的不知道你为什么被否决。解释得很好:)否决票是基于贾斯汀最初的答案,这只是第一行。虽然帮不上什么忙,但他还是排在了队伍的最前面。随着我的观看,它变得越来越充实。或者像我在另一个答案中评论的那样使用IReadOnlyList
(从.NET 4.5开始)。strings.Cast()
在语义上更加正确,因为所有字符串都是object
类型。感谢大家,Tim奖颁给你,因为你是第一个注意到类类型差异与接口的人。我不是第一个注意到这一点吗?我不在乎分数,所以就这样说吧:)啊,普鲁克,你完全正确,你让蒂姆·罗杰斯在我看来领先了90秒。感谢您的帮助。如果@BarryFandango需要列表功能,在.NET 4.5及更高版本中,他可以使用void方法(IReadOnlyList对象)
。接口IReadOnlyList
在T
中是协变的,List
和T[]
以及其他接口实现IReadOnlyList
。