我编写了以下代码,以尝试提供类型安全的接口:
namespace MWE
{
public abstract class C {}
public class A : C {}
public class B : C {}
public class Container<T> where T : C
{
public readonly T Value;
public static implicit operator T(Container<C> c)
{
return c.Value;
}
}
public interface IWrapper<out TC> where TC : C {}
public class Foo
{
public Foo(IWrapper<Container<C>> wrapper) {}
}
}
不幸的是,这无法编译。 Compiler<C>
构造函数wrapper
的{{1}}部分导致编译器产生以下错误:
在通用类型或方法“ IWrapper
”中,类型“ MFE.Container ”不能用作类型参数“ TC”。没有从'MFE.Container '到'MFE.C'的隐式引用转换。
为了在通用接口“ MFE.IWrapper”中将其用作参数“ TC”,必须将类型“ MFE.Container ”转换为“ WeirdTestStuff.C”。
我无法弄清楚问题出在哪里,因为转换的协方差似乎存在,甚至存在从Foo
到Container<T>
定义的隐式转换。从T
开始,我认为它应该像这样工作。
我想尽可能保持T : C
的构造函数。
我希望有人可以为我指出这个问题的解决方案
答案 0 :(得分:2)
甚至是从容器到T的隐式转换
是的,但这不是编译器所需要的。它要求:
隐式引用转换
(我的重点)
隐式引用转换不是任何用户定义的运算符提供的转换,仅当一种类型(直接或通过中间类型)从另一 1 派生时才被允许。
editModalText() {
let modalMessage="Hello, my name is /# Ann #/. I'm working for /# IStaff #/, could you please call me back"
return (
<div>
{modalMessage
.split("/")
.map((text, idx) =>
text.includes("#") ? this.replaceCharacter(idx, text) : text,
)}
</div>
)
}
replaceCharacter(idx, text) {
let formattedText = text.replace(/#/g, " ")
return (
<input
key={idx}
value={formattedText}
onChange={e => this.setState({input:e.target.value})}
/>
)
}
具有 Container
,并且可以通过用户定义的运算符转换为C
,但这不足以使其成为 C。您的问题过于抽象,无法在此处说明解决方案-C
应该是非通用的,并且是从Container
派生的吗?这是“关闭”编译器的明显方法,但可能无法解决您的实际问题。
您不能在运行时使用泛型来设置类型的基类型。
1 这些是埃里克·利珀特(Eric Lippert)的Representation-preserving conversions