C# 告诉编译器泛型类型存在隐式转换

C# 告诉编译器泛型类型存在隐式转换,c#,generics,compiler-errors,C#,Generics,Compiler Errors,考虑以下代码 class SomeType1 { } 类SomeType2 { } 类组合类型 { 公共静态隐式运算符组合类型(SomeType1源) { 返回新的组合类型 { ... }; } 公共静态隐式运算符CombinedType(SomeType2源) { 返回新的组合类型 { ... }; } } void方法() { var listOfType1=新列表(); DoSomethingWith(类型1列表); var listOfType2=新列表(); DoSomethingWi

考虑以下代码

class SomeType1
{
}
类SomeType2
{
}
类组合类型
{
公共静态隐式运算符组合类型(SomeType1源)
{
返回新的组合类型
{
...
};
}
公共静态隐式运算符CombinedType(SomeType2源)
{
返回新的组合类型
{
...
};
}
}
void方法()
{
var listOfType1=新列表();
DoSomethingWith(类型1列表);
var listOfType2=新列表();
DoSomethingWith(类型2列表);
}
无效剂量含(IEnumerable stuff)
{
IEnumerable converted=stuff.Select(i=>(CombinedType)i);
...
}
这与

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


然而,我知道当
T
SomeType1
SomeType2
时,
T
CombinedType
之间存在隐式转换。我如何告诉编译器这应该是可能的?我无法在泛型方法上添加
其中T:CombinedType
,因为这不是真的。

您可以创建一个共享的虚拟接口,如
接口ICombinedType{}
,使所有3个类都实现它,然后将
其中T:ICombinedType
添加到泛型方法中。

您可以创建一个共享的虚拟接口,如
接口ICombinedType{}
,使所有3个类都实现它,然后将
其中T:ICombinedType
添加到泛型方法。

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

例如:

CombinedType c = new SomeType1();
变成:

CombinedType c = CombinedType.op_Implicit(new SomeType1());
JIT不知道如何插入这些方法调用。然而,泛型是在JIT时间扩展的,而JIT时间正是您希望这种情况发生的时候

不要忘记,您的代码还允许某人传入一个
t
,该类型不能转换为
组合类型


然而,你有一些选择

一是:

void DoSomethingWith<T>(IEnumerable<T> stuff)
{
    IEnumerable<CombinedType> converted = stuff.Select(i => i switch
    {
        SomeType1 s1 => (CombinedType)s1,
        SomeType2 s2 => (CombinedType)s2,
        _ => throw ...
    });
}
void DoSomethingWith(IEnumerable stuff)
{
IEnumerable converted=stuff.Select(i=>i开关
{
SomeType1 s1=>(组合类型)s1,
SomeType2 s2=>(组合类型)s2,
_=>扔。。。
});
}
另一种是:

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());
    ...
}
公共接口IConvertibleTombinedType
{
CombinedType ConvertToCombinedType();
}
公共类SomeType1:IConvertibleTombinedType
{
//…或者去掉隐式转换,把逻辑放在这里
public CombinedType ConvertToCombinedType()=>this;
}
公共类SomeType2:IConvertibleTombinedType
{
...
}
void DoSomethingWith(IEnumerable stuff),其中T:IConvertibleTombinedType
{
IEnumerable converted=stuff.Select(i=>ConvertToCombinedType());
...
}

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

例如:

CombinedType c = new SomeType1();
变成:

CombinedType c = CombinedType.op_Implicit(new SomeType1());
JIT不知道如何插入这些方法调用。然而,泛型是在JIT时间扩展的,而JIT时间正是您希望这种情况发生的时候

不要忘记,您的代码还允许某人传入一个
t
,该类型不能转换为
组合类型


然而,你有一些选择

一是:

void DoSomethingWith<T>(IEnumerable<T> stuff)
{
    IEnumerable<CombinedType> converted = stuff.Select(i => i switch
    {
        SomeType1 s1 => (CombinedType)s1,
        SomeType2 s2 => (CombinedType)s2,
        _ => throw ...
    });
}
void DoSomethingWith(IEnumerable stuff)
{
IEnumerable converted=stuff.Select(i=>i开关
{
SomeType1 s1=>(组合类型)s1,
SomeType2 s2=>(组合类型)s2,
_=>扔。。。
});
}
另一种是:

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());
    ...
}
公共接口IConvertibleTombinedType
{
CombinedType ConvertToCombinedType();
}
公共类SomeType1:IConvertibleTombinedType
{
//…或者去掉隐式转换,把逻辑放在这里
public CombinedType ConvertToCombinedType()=>this;
}
公共类SomeType2:IConvertibleTombinedType
{
...
}
void DoSomethingWith(IEnumerable stuff),其中T:IConvertibleTombinedType
{
IEnumerable converted=stuff.Select(i=>ConvertToCombinedType());
...
}

是个好主意,但我实际上没有访问
SomeType1
的源代码,它来自一个库。这是个好主意,但我实际上没有访问
SomeType1
的源代码,它来自一个库。我认为选项1对我有帮助。我在另一个答案中提到,我无法访问
SomeType1
的源代码,因此无法添加其他接口。@Steztric这类信息将非常有助于在您的问题中包含。
switch
方法也可以放在
CombinedType
中。也就是说,如果您在
CombinedType
类中放置了以下方法:
publicstaticcombinedType创建(T){switch(T){case-sometype1st1:return st1;case-sometype2st2:return st2;default:throw-new-ArgumentException();}
(或类似于C#8语法)。然后您可以将select编写为:
IEnumerable converted=stuff.select(CombinedType.Create)
。我认为选项1对我有帮助。我在另一个答案中提到,我无法访问
SomeType1
的源代码,因此无法添加其他接口。@Steztric这类信息将非常有助于在您的问题中包含。
switch
方法也可以放在
CombinedType
中。也就是说,如果您在
CombinedType
类中放置了以下方法:
publicstaticcombinedType创建(T){switch(T){case-sometype1st1:return st1;case-sometype2st2:return st2;default:throw-new-ArgumentException();}
(或类似于C#8语法)。然后您可以将select编写为:
IEnumerable converted=stuff.select(CombinedType.Create)
。如何调用
DoSomethingWith
?做