如何显式地转换'object'类型的变量以满足多类型泛型约束?

Mar*_*eIV 8 c# generics casting

我们有一个通用的扩展方法,它只适用于支持INotifyCollectionChanged和IEnumerable接口的对象.它是这样写的:

public static class SomeExtensions
{
    public static void DoSomething<T>(this T item)
    where T : INotifyCollectionChanged, IEnumerable
    {
        // Do something
    }
}
Run Code Online (Sandbox Code Playgroud)

以下编译很好,因为ObservableCollection<string>实现了两个接口,并且由于'var'关键字,knownType是强类型的:

var knownType = new ObservableCollection<string>();
knownType.DoSomething();
Run Code Online (Sandbox Code Playgroud)

但是,我们试图从ValueConverter中调用它.问题是传入的值是类型的object,即使我们可以测试传入的对象确实实现了两个接口,我们也无法弄清楚如何显式地转换它,以便我们可以调用该泛型扩展方法.这显然不起作用(显然)......

object unknownType = new ObservableCollection<string>();
((INotifyCollectionChanged,IEnumerable)unknownType).DoSomething();
Run Code Online (Sandbox Code Playgroud)

那么如何将对象转换为多个接口以便调用泛型呢?甚至不确定它是否可行.

Dav*_*vid 2

我能想到的最干净的方法是dynamic。但是,由于扩展方法不能很好地配合dynamic(请参见下文),因此您必须显式引用扩展方法。

Extensions.DoSomething(unknownType as dynamic);
Run Code Online (Sandbox Code Playgroud)

编辑作为对我在这里遇到的问题的警告,请注意,使用显式dyanmic作为类型参数(通过DoSomething<dynamic>)调用方法将不起作用- 当尝试匹配多个约束时,它会导致编译错误。此外,当不使用多个约束时,这会导致dynamic根据传递变量的编译时类型而不是运行时类型进行解析。

这将导致对 的调用Extensions.UnknownType<dynamic>dynamic其中的 会在运行时解析 - 这意味着它将使用给定参数的完全派生类型。只要这个参数实现了所需的接口,就可以了。

请小心,因为与许多dynamic代码一样,这可能会遇到直到运行时才会出现的问题。谨慎使用!

如果您使用相同的通用参数进行多次调用,则最好在转换器中添加通用帮助器方法,然后使用value as dynamic

附录

使用 时dynamic,针对对象调用的任何内容都dynamic将尝试在运行时解析为给定类型的成员,但不会查找扩展方法,因为它们本质上存在于完全不同的类(通常是不同的程序集中)中。