将泛型类转换为接口

Kol*_*lja 4 c# generics clr casting

将通用类转换为它正在实现的接口时遇到问题.

我的代码是这样的:

interface foo
{
    void foobar();
}

class bar: foo
{
    public void foobar()
    {
        throw new NotImplementedException();
    }
}
Run Code Online (Sandbox Code Playgroud)

现在我的工厂通过界面创建我的类的实例,主要是一个简单的微内核(服务定位器).我会在这里简化它.通常它会从配置中查找实现类,而工厂将类型视为T,但这与我遇到的问题无关.

public static class Factory
{


    public static Lazy<foo> CreateLazyInstance()
    {
        Lazy<foo> instance;


        Type type = typeof(bar);

        Type lazyType = typeof(Lazy<>);
        Type toContruct = lazyType.MakeGenericType(type);

        instance = (Lazy<foo>)Activator.CreateInstance(toContruct);

        return instance;
    }
}
Run Code Online (Sandbox Code Playgroud)

如果失败的话:

instance = (Lazy<foo>)Activator.CreateInstance(toContruct);
Run Code Online (Sandbox Code Playgroud)

并声明InvalidCastException无法将类型强制转换Lazy<bar>Lazy<foo>.

有没有办法告诉CLR这个演员会工作还是解决这个问题?

Jon*_*eet 5

不 - Lazy<T>不变的 - 所以a Lazy<string>不是Lazy<object>例如.(正如评论中所指出的那样,它不能被声明为协变T,因为它是一个类,而不是接口或委托.)

但是,您可以轻松地将一个转换为另一个:

static Lazy<TOutput> CreateLazyProxy<TInput, TOutput>
    (Lazy<TInput> input) where TInput : TOutput
{
    return new Lazy<TOutput>(() => input.Value);
}
Run Code Online (Sandbox Code Playgroud)

此外,Func<T> 协变,所以这也将工作:

static Lazy<TOutput> CreateLazy<TInput, TOutput>(Func<TInput> func)
    where TInput : TOutput
{
    return new Lazy<TOutput>(func);
}
Run Code Online (Sandbox Code Playgroud)

(并不是说你特别需要一种方法 - 如果你一个Func<TInput>,只需Lazy<TOutput>直接构建一个.)