无法使用动态C#转换通用基元

jon*_*yer 2 c#

我试图检查我在返回类型中向下转换的结果是否可转换为哪种派生类型.我正在检查的派生类型是具有协变参数的泛型.我使用is运算符将其强制转换为动态类型.我相信,因为泛型参数是一个原始类型的bool,它不起作用.奇怪的是在监视窗口中,结果是预期的,但代码执行不是.我不确定是否有遗漏或这是一个错误.这是预期的行为吗?

我通过检查结果是否是泛型,然后获取类型参数并使用MakeGenericType和'dynamic result = Convert.ChangeType'来解决这个问题.

这是一个简单的示例应用程序来演示.

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");
Run Code Online (Sandbox Code Playgroud)

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

样品申请

Jon*_*eet 5

dynamic在执行时不存在作为不同类型.动态类型由C#编译器结合一些非常狡猾的框架功能执行.但运行时根本不知道它.

你有效地询问是否testBool实现IEnumerable<object>- 而不是.(这就是IL参与测试的内容.)

有一个错误,但它在Watch窗口处理 - 而不是在常规执行中.我已经看到Watch窗口不像常规代码那样的各种情况.如果这种情况特别严重,我不会感到惊讶dynamic.

就行为而言List<string>:

  • List<string>实现IEnumerable<dynamic>由于协方差IEnumerable<T>(即它实现IEnumerable<object>)
  • List<string> 没有实现IList<dynamic>,只是一个没有涉及差异的例子.

如果您认为使用dynamic作为类型参数将有效地检查"这种类型的实现IEnumerable<T>是否T会动态确定某种类型",但事实并非如此.您可以使用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");
}
Run Code Online (Sandbox Code Playgroud)

请注意,如果您处理完全未知的值,这种事情可能会很危险 - 如果您尝试使用实现(例如)的值,IEnumerable<string>并且IEnumerable<bool>将以与编译相同的方式抛出异常尝试ShowList使用该值调用的时间错误,因为类型推断找不到"最佳" T.