Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/matlab/13.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 强制转换要列出的对象列表vs IList_C#_Casting - Fatal编程技术网

C# 强制转换要列出的对象列表vs IList

C# 强制转换要列出的对象列表vs IList,c#,casting,C#,Casting,刚刚遇到这个: Func<List<object>> foo = () => new List<object>(); List<string> s = (List<string>)foo(); IList<string> s1 = (IList<string>)foo(); Func foo=()=>newlist(); List s=(List)foo(); IList s1=(IList)foo();

刚刚遇到这个:

Func<List<object>> foo = () => new List<object>();
List<string> s = (List<string>)foo();
IList<string> s1 = (IList<string>)foo();
Func foo=()=>newlist();
List s=(List)foo();
IList s1=(IList)foo();

编译器抱怨强制转换到列表(有道理),但对IList却只字不提。让我想知道这是为什么?

第一行在编译时失败,第二行在运行时出现“无法将'System.Collections.Generic.List
1[System.object]'类型的对象强制转换为'System.Collections.Generic.IList
1[System.String]'”异常


如果您看这个问题(),答案将阐明此编译工作的原因,并为满足提供的条件的类提供一个示例。

编译器知道
列表不能是
列表

因此,它给出了一个编译器错误

但是,如果
列表
实际上是某个派生类,该派生类也实现了
IList
,则第二次强制转换可能会成功

如果两种类型都不是接口,或者一种类型是不相关的接口,而另一种类型是密封的(或结构),则只能从转换中获得编译时错误

引用规范(§6.4.2)

显式引用转换为:

  • 从对象和动态到任何其他引用类型
  • 从任何类类型S到任何类类型T,只要S是T的基类
  • 从任何类类型S到任何接口类型T,前提是S未密封且S未实现T。
  • 从任何接口类型S到任何类类型T,前提是T未密封或T实现S。
  • 从任何接口类型S到任何接口类型T,前提是S不是从T派生的
  • [剪报]
(增加重点)


提供的…
子句排除了实际隐含的转换。

已知为
列表的对象可能实现
IList
以及
IList
,因此强制转换可能会成功。在这种情况下它不能,因为我们知道语句仅仅是<代码>新的表()/<代码>,但是编译器不这么认为。您可能已经扩展了
列表
,并实现了另一个,例如

// not recommended, but second cast works
public class MyWeirdList : List<object>, IList<string>
//不推荐,但第二次强制转换有效
公共类MyWeirdList:List,IList

已知为
列表
的对象不可能也是
列表
,因为只能从单个类型继承

public class MyWeirdList : List<object>, List<string> // compiler error
公共类MyWeirdList:List,List//编译器错误
如果
List
被密封,两个强制转换都将无效,因为这样编译器就可以确定类无法实现
IList
。您可以改为使用此类来尝试此操作:

public sealed class SealedList<T> : List<T> { }
公共密封类密封列表:列表{}

我很确定最后一行在运行时会失败。确实会失败,但有趣的是编译器会捕获第一个案例。是的,会的。只是想知道它为什么会编译。@ReedCopsey,我应该声明我对编译器错误感兴趣。我同意;这很有趣。@ReedCopsey,编译器知道对
列表
没有隐式强制转换操作,但是
IList
的实现者可能能够?而另一种类型是
密封的
?这是因为它知道它不能被继承者覆盖吗?@MichaelPerrenoud:justice.Hm,这使它成为一个有效的构造:Func foo=()=>new List();var s1=(IFoo)foo();“出乎意料,真的。”尤金:有时出乎意料,但必须是合法的。在过去的一周里,我已经在真实代码中不止一次这样做了。感谢您引用规范!