Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/307.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# 为什么要将角色转换为“IEnumerable<;T>;`允许,但必须是“列表”<;T>;`用一般方法_C#_Generics_Types_Casting - Fatal编程技术网

C# 为什么要将角色转换为“IEnumerable<;T>;`允许,但必须是“列表”<;T>;`用一般方法

C# 为什么要将角色转换为“IEnumerable<;T>;`允许,但必须是“列表”<;T>;`用一般方法,c#,generics,types,casting,C#,Generics,Types,Casting,我很确定我没有找到明显的答案,但为什么: public static void Foo(IEnumerable<string> strings) { } public static void Bar<T>(IEnumerable<T> ts) { Foo((IEnumerable<string>)ts); } publicstaticvoidfoo(IEnumerable字符串){} 公共静态空白栏(IEnumerable ts) {

我很确定我没有找到明显的答案,但为什么:

public static void Foo(IEnumerable<string> strings) { }

public static void Bar<T>(IEnumerable<T> ts)
{
    Foo((IEnumerable<string>)ts);
}
publicstaticvoidfoo(IEnumerable字符串){}
公共静态空白栏(IEnumerable ts)
{
Foo((IEnumerable)ts);
}
是允许的,而这:

public static void Foo(List<string> strings) { }

public static void Bar<T>(List<T> ts)
{
    Foo((List<string>)ts);
}
publicstaticvoidfoo(列表字符串){}
公共静态空栏(列表ts)
{
Foo((列表)ts);
}

CS0030无法将类型“System.Collections.Generic”转换为类型“System.Collections.Generic”。?两者都有可能在运行时失败,也都有可能在运行时成功。什么样的语言规则支配着这一点?

我认为这是以下问题的一个边缘案例:

我同意,在这种情况下,它看起来很奇怪,因为它不可能从扩展字符串的内容中进行转换(字符串类是密封的),但我猜规则是不能将
List
强制转换为
List
,因为在t是扩展类SomethingElse或实现接口SomethingElse的类的情况下,可能会调用该方法

e、 g:

public static void Foo(List<string> strings) { }

public static void Bar<T>(List<T> ts)
{
    Foo((List<MyInterface>)ts);
}

public static void OtherMethod1()
{
    Bar<MyClass>(new List<MyClass>)
}

public static void OtherMethod2()
{
    Bar<MyInterface>(new List<MyInterface>)
}

public classs MyClass : MyInterface
{
}
publicstaticvoidfoo(列表字符串){}
公共静态空栏(列表ts)
{
Foo((列表)ts);
}
公共静态void OtherMethod1()
{
酒吧(新名单)
}
公共静态void OtherMethod2()
{
酒吧(新名单)
}
公共类MyClass:MyInterface
{
}
因此,由于可以编写类似于OtherMethod1的方法,但在运行时失败,因此编译器不允许整个场景。

不过,同样,密封类似乎是一种奇怪的边缘情况,如果Microsoft愿意,可能会允许这种情况。

我认为这是以下问题的边缘情况示例:

我同意,在这种情况下,它看起来很奇怪,因为它不可能从扩展字符串的内容中进行转换(字符串类是密封的),但我猜规则是不能将
List
强制转换为
List
,因为在t是扩展类SomethingElse或实现接口SomethingElse的类的情况下,可能会调用该方法

e、 g:

public static void Foo(List<string> strings) { }

public static void Bar<T>(List<T> ts)
{
    Foo((List<MyInterface>)ts);
}

public static void OtherMethod1()
{
    Bar<MyClass>(new List<MyClass>)
}

public static void OtherMethod2()
{
    Bar<MyInterface>(new List<MyInterface>)
}

public classs MyClass : MyInterface
{
}
publicstaticvoidfoo(列表字符串){}
公共静态空栏(列表ts)
{
Foo((列表)ts);
}
公共静态void OtherMethod1()
{
酒吧(新名单)
}
公共静态void OtherMethod2()
{
酒吧(新名单)
}
公共类MyClass:MyInterface
{
}
因此,由于可以编写类似于OtherMethod1的方法,但在运行时失败,因此编译器不允许整个场景。

不过,同样,密封类似乎是一种奇怪的边缘情况,如果Microsoft愿意,它可能被允许使用。

这是否回答了您的问题?特别是这样一句话:“它是安全的,因为
IEnumerable
不公开任何接受T的方法。”@BagusTesa特别将T定义为仅适用于IEnumerable的out,它强制您声明IEnumerable不接受TNo类型的任何内容,而且“重复”问题似乎也不接受。我知道什么是通用差异,但允许对任意
T
进行从
IEnumerable
IEnumerable
的转换是不安全的
IEnumerable
必须是协变和逆变,才能在运行时永不失败。这是否回答了您的问题?特别是这样一句话:“它是安全的,因为
IEnumerable
不公开任何接受T的方法。”@BagusTesa特别将T定义为仅适用于IEnumerable的out,它强制您声明IEnumerable不接受TNo类型的任何内容,而且“重复”问题似乎也不接受。我知道什么是通用差异,但允许对任意
T
进行从
IEnumerable
IEnumerable
的转换是不安全的
IEnumerable
必须是协变和逆变,才能在运行时永不失败。但使用
T=object
调用
IEnumerable
版本也会在运行时失败,但这是允许的。为什么?强制转换允许在运行时失败。编译器不允许的是可以工作的强制转换,但在尝试调用强制转换类型上的有效方法时失败。在IEnumerable上,如果您从T转换到对象,并且转换成功,则没有任何方法会中断。这是一份清单。请参阅链接的示例/duplicate。但是使用
T=object
调用
IEnumerable
版本也会在运行时失败,但这是允许的。为什么?强制转换允许在运行时失败。编译器不允许的是可以工作的强制转换,但在尝试调用强制转换类型上的有效方法时失败。在IEnumerable上,如果您从T转换到对象,并且转换成功,则没有任何方法会中断。这是一份清单。请参阅链接的示例/副本。