首页 > 解决方案 > 告诉编译器泛型类型存在隐式转换

问题描述

考虑以下代码;

class SomeType1
{
}

class SomeType2
{
}

class CombinedType
{
    public static implicit operator CombinedType(SomeType1 source)
    {
        return new CombinedType
        {
            ...
        };
    }

    public static implicit operator CombinedType(SomeType2 source)
    {
        return new CombinedType
        {
            ...
        };
    }
}

void SomeMethod()
{
    var listOfType1 = new List<SomeType1>();
    DoSomethingWith(listOfType1);

    var listOfType2 = new List<SomeType2>();
    DoSomethingWith(listOfType2);
}

void DoSomethingWith<T>(IEnumerable<T> stuff)
{
    IEnumerable<CombinedType> converted = stuff.Select(i => (CombinedType) i);
    ...
}

这失败了

错误 CS0030 无法将类型“T”转换为“CombinedType”

但是,我知道在is orT之间存在隐式转换。我如何告诉编译器这应该是可能的?我不能添加通用方法,因为那不是真的。CombinedTypeTSomeType1SomeType2where T : CombinedType

标签: c#genericscompiler-errors

解决方案


隐式转换只是编译器在编译时插入的方法调用。

例如:

CombinedType c = new SomeType1();

变成:

CombinedType c = CombinedType.op_Implicit(new SomeType1());

JIT 不知道插入这些方法调用。然而,泛型是在 JIT 时扩展的,这是您希望发生这种情况的时候。

不要忘记您的代码还允许某人传入T不可转换为CombinedType.


但是,您有几个选择。

一种是:

void DoSomethingWith<T>(IEnumerable<T> stuff)
{
    IEnumerable<CombinedType> converted = stuff.Select(i => i switch
    {
        SomeType1 s1 => (CombinedType)s1,
        SomeType2 s2 => (CombinedType)s2,
        _ => throw ...
    });
}

另一个是这样的:

public interface IConvertibleToCombinedType
{
    CombinedType ConvertToCombinedType();
}

public class SomeType1 : IConvertibleToCombinedType
{
    // ... or get rid of the implicit conversion, and put the logic here
    public CombinedType ConvertToCombinedType() => this;
}

public class SomeType2 : IConvertibleToCombinedType
{
   ...
}

void DoSomethingWith<T>(IEnumerable<T> stuff) where T : IConvertibleToCombinedType
{
    IEnumerable<CombinedType> converted = stuff.Select(i => ConvertToCombinedType());
    ...
}

推荐阅读