C# 泛型转换方法抛出InvalidCastException

C# 泛型转换方法抛出InvalidCastException,c#,generics,runtime,.net,C#,Generics,Runtime,.net,我想实现相同的简单泛型转换方法,但在运行时我遇到了一个错误 因此,情况非常简单。我有相同的服务返回给我类型为External的项目列表。我有自己的WrapperExternal类,它简单地包装这个类并向它公开一些附加功能。我还有一些从WrapExternal继承并添加不同功能的类 我想创建一个通用方法,该方法接受外部列表项列表并返回指定类型的项列表 我的申请代码: static void Main(string[] args) { var items = GetI

我想实现相同的简单泛型转换方法,但在运行时我遇到了一个错误

因此,情况非常简单。我有相同的服务返回给我类型为External的项目列表。我有自己的WrapperExternal类,它简单地包装这个类并向它公开一些附加功能。我还有一些从WrapExternal继承并添加不同功能的类

我想创建一个通用方法,该方法接受外部列表项列表并返回指定类型的项列表

我的申请代码:

    static void Main(string[] args)
    {
        var items = GetItemsFromServer();
        var converted = ConvertItems<SubWrapperExternal>(items).ToList();
    }

    public static IEnumerable<T> ConvertItems<T>(IEnumerable<External> externalItems) where T : WrapperExternal
    {
        return externalItems
            .Where( item => true)
            .Select(item => (T)item);
    }
namespace ConsoleApplication1
{
class Program
{
    static void Main(string[] args)
    {
        var items = GetItemsFromServer();

        var converted = ConvertItems<SubWrapperExternal>(items).ToList();

    }

    private static List<External> GetItemsFromServer()
    {
        return new List<External>
        {
            new External{Name = "A"},
            new External{Name = "B"},
            new External{Name = "C"},
        };
    }

    public static IEnumerable<T> ConvertItems<T>(IEnumerable<External> externalItems) where T : WrapperExternal
    {
        return externalItems
            .Where( item => true)
            .Select(item => (T)item);
    }
}

class External
{
    public string Name { get; set; }

}

class WrapperExternal
{
    public External External { get; private set; }

    public WrapperExternal(External external)
    {
        External = external;
    }

    public static explicit operator WrapperExternal(External item)
    {
        return item != null ? new WrapperExternal(item) : null;
    }

    public static implicit operator External(WrapperExternal item)
    {
        return item != null ? item.External : null;
    }
}

class SubWrapperExternal : WrapperExternal
{
    public SubWrapperExternal(External external)
        : base(external)
    {
    }

    public static explicit operator SubWrapperExternal(External item)
    {
        return item != null ? new SubWrapperExternal(item) : null;
    }

    public static implicit operator External(SubWrapperExternal item)
    {
        return item != null ? item.External : null;
    }
}
}
你知道我怎样才能让它工作吗

测试应用程序代码:

    static void Main(string[] args)
    {
        var items = GetItemsFromServer();
        var converted = ConvertItems<SubWrapperExternal>(items).ToList();
    }

    public static IEnumerable<T> ConvertItems<T>(IEnumerable<External> externalItems) where T : WrapperExternal
    {
        return externalItems
            .Where( item => true)
            .Select(item => (T)item);
    }
namespace ConsoleApplication1
{
class Program
{
    static void Main(string[] args)
    {
        var items = GetItemsFromServer();

        var converted = ConvertItems<SubWrapperExternal>(items).ToList();

    }

    private static List<External> GetItemsFromServer()
    {
        return new List<External>
        {
            new External{Name = "A"},
            new External{Name = "B"},
            new External{Name = "C"},
        };
    }

    public static IEnumerable<T> ConvertItems<T>(IEnumerable<External> externalItems) where T : WrapperExternal
    {
        return externalItems
            .Where( item => true)
            .Select(item => (T)item);
    }
}

class External
{
    public string Name { get; set; }

}

class WrapperExternal
{
    public External External { get; private set; }

    public WrapperExternal(External external)
    {
        External = external;
    }

    public static explicit operator WrapperExternal(External item)
    {
        return item != null ? new WrapperExternal(item) : null;
    }

    public static implicit operator External(WrapperExternal item)
    {
        return item != null ? item.External : null;
    }
}

class SubWrapperExternal : WrapperExternal
{
    public SubWrapperExternal(External external)
        : base(external)
    {
    }

    public static explicit operator SubWrapperExternal(External item)
    {
        return item != null ? new SubWrapperExternal(item) : null;
    }

    public static implicit operator External(SubWrapperExternal item)
    {
        return item != null ? item.External : null;
    }
}
}

转换运算符是泛型的faff-泛型不支持任何静态运算符重载。因此,T cast正在执行非转换类型检查,泛型需要为每个可能的T使用相同的IL,记住-一个基本的castclass

做你想做的事情的唯一简单方法是使用dynamic欺骗:


由于特定于C的动态提供程序知道C的所有通用规则,因此它知道转换运算符,并将根据需要应用它们。与此相关的性能代价很小,但它并不像乍一看那样糟糕,因为该策略在每种类型中缓存为IL一次-它不会执行每项反射。

您能否不使用现有的.OfType扩展方法?OfType返回从集合类型继承的集合元素。我的WrapperExternal没有从External继承type@MarcGravell你不能。这一例外具有误导性。他想将外部项列表转换为T项列表。其中T是外部包装器。但是这两者之间没有定义强制转换,外部也不是从WrapperExternal派生的。@Herdo啊,我没有看到不相关的类型;幸运的是,有一种方法可以实现这一点;P