简体   繁体   English

无法使用动态C#强制转换泛型基元

[英]Cannot Cast Generic Primitive with dynamic C#

I am trying to check if a result, which I downcast in the return type is convertible to which derived type. 我正在尝试检查返回类型中向下转换的结果是否可转换为哪个派生类型。 The derived type I am checking against is a generic with a covariant argument. 我要检查的派生类型是带有协变量参数的泛型。 I am using the is operator to cast it to a dynamic type. 我正在使用is运算符将其转换为动态类型。 I believe since the generic argument is a primitive type bool that it is not working. 我相信,由于泛型参数是基本类型的布尔型,因此无法正常工作。 Strangely in the watch window the result is as expected, but the code execution is not. 在监视窗口中,奇怪的是结果与预期的一样,但是代码执行却没有。 I'm not sure if there is something i'm missing or this is a bug. 我不确定是否缺少某些东西,或者这是一个错误。 Is this expected behavior? 这是预期的行为吗?

I have worked around this by checking if the result is a generic and then getting the type argument and using MakeGenericType combined with a 'dynamic result = Convert.ChangeType'. 我已经通过检查结果是否为泛型来解决此问题,然后获取类型参数并结合使用MakeGenericType和“动态结果= Convert.ChangeType”。

Here is a simple sample application to demonstrate. 这是一个简单的示例应用程序来演示。

var testBool = new List<bool>();     // Primitive
var testString = new List<string>(); // Class

if (testBool is IEnumerable<bool>)
    Console.WriteLine("Test Bool");
if (testBool is IEnumerable<dynamic>)
    Console.WriteLine("Test Bool - Dynamic");
if (testString is IEnumerable<string>)
    Console.WriteLine("Test string");
if (testString is IEnumerable<dynamic>)
    Console.WriteLine("Test string - Dynamic");

Notes: .NET Core 2.1, Visual Studio 2017, C# 注意:.NET Core 2.1,Visual Studio 2017,C#

样品申请

dynamic doesn't exist at execution time as a distinct type. dynamic在执行时并不以独特的类型存在。 Dynamic typing is performed by the C# compiler in conjunction with some very cunning framework features. 动态类型由C#编译器结合一些非常狡猾的框架功能执行。 The runtime doesn't know about it at all though. 运行时完全不知道它。

You're effectively asking whether testBool implements IEnumerable<object> - and it doesn't. 您实际上是在问testBool是否实现IEnumerable<object> -否。 (That's what the IL involved is testing for.) (这就是所涉及的IL正在测试的东西。)

There is a bug, but it's in the Watch window handling - not in the regular execution. 有一个错误,但在“监视”窗口中处理- 不在常规执行中。 I've seen various situations where the Watch window doesn't quite behave like regular code. 我已经看到过各种情况,其中“监视”窗口的行为不像常规代码。 I wouldn't be surprised if this was particularly acute around dynamic . 如果dynamic如此尖锐,我不会感到惊讶。

In terms of the behaviour of the List<string> : List<string>的行为而言:

  • List<string> implements IEnumerable<dynamic> due to the covariance of IEnumerable<T> (ie it implements IEnumerable<object> ) List<string>由于IEnumerable<T>的协方差而实现了IEnumerable<dynamic> IEnumerable<T> (即,它实现了IEnumerable<object>
  • List<string> doesn't implement IList<dynamic> , as just one example where there's no variance involved. List<string> 并没有实现IList<dynamic> ,这只是一个不涉及方差的示例。

If you were thinking that using dynamic as a type argument would effectively check "does this type implement IEnumerable<T> for some type T which will be determined dynamically", it doesn't. 如果您认为使用dynamic作为类型参数可以有效地检查“此类型是否为将动态确定的T类型实现IEnumerable<T> ”,则不是。 You can use dynamic to perform execution-time type inference though: 可以使用dynamic来执行执行时类型推断:

dynamic d = ...; // Whatever value you're interested in
ShowList(d);

private void ShowList<T>(IEnumerable<T> list)
{
    Console.WriteLine($"Implements IEnumerable<{typeof(T)}>");
}

private void ShowList(object backstop)
{
    Console.WriteLine("I guess it doesn't implement IEnumerable<T> at all");
}

Note that this sort of thing can be dangerous if you're dealing with entirely unknown values - if you try this with a value that implements (say) IEnumerable<string> and IEnumerable<bool> , an exception will be thrown in the same way that you'd get a compile-time error trying to call ShowList with that value, as type inference doesn't find a "best" T . 请注意,如果您要处理完全未知的值,这种事情可能很危险-如果使用实现(例如) IEnumerable<string>IEnumerable<bool>的值进行尝试,则会以相同的方式引发异常尝试使用该值调用ShowList时会遇到编译时错误,因为类型推断找不到“最佳” T

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM