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
?做