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

时间:2018-07-25 17:48:59

标签: c#

我正在尝试检查返回类型中向下转换的结果是否可转换为哪个派生类型。我要检查的派生类型是带有协变量参数的泛型。我正在使用is运算符将其转换为动态类型。我相信,由于泛型参数是基本类型的布尔型,因此无法正常工作。在监视窗口中,奇怪的是结果与预期的一样,但是代码执行却没有。我不确定是否缺少某些东西,或者这是一个错误。这是预期的行为吗?

我通过检查结果是否为通用变量,然后获取类型参数并结合使用MakeGenericType和“动态结果= 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");

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

Sample Application

1 个答案:

答案 0 :(得分:5)

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

您实际上是在问testBool是否实现了IEnumerable<object>-并没有实现。 (这就是相关IL正在测试的内容。)

有一个错误,但是在监视窗口中处理-在常规执行中不是。我已经看到过各种情况,其中“监视”窗口的行为不像常规代码。如果这种情况在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");
}

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