泛型c#类中的链式隐式运算符

泛型c#类中的链式隐式运算符,c#,operator-overloading,abstract-class,C#,Operator Overloading,Abstract Class,对于以下通用c#类,我想将T转换为K: public abstract class ValueType<T,K> : IValueType<T> where K : ValueType<T,K>,new() { public abstract T Value { get; set; } public static implicit operator ValueType<T,K>(T val) {

对于以下通用c#类,我想将T转换为K:

public abstract class ValueType<T,K> : IValueType<T> where K : ValueType<T,K>,new()
{     
    public abstract T Value { get; set; }     

    public static implicit operator ValueType<T,K>(T val) 
    {         
        K k = new K();
        k.Value = val;
        return k;    
    }
}
但下面的示例仍然抱怨它无法转换:

public class Test : ValueType<int, Test>
{
    public override int Value{ get; set; }
}

Test t = 6; //complains it's unable to be converted
Console.WriteLine(t.Value);
公共类测试:ValueType
{
公共重写int值{get;set;}
}
试验t=6//抱怨它无法转换
控制台写入线(t值);
如果可能的话,我真的想避免显式地强制转换


这个问题延伸到我之前提出的问题。

据我所知,我认为您无法将强制类型转换链接在一起,对此表示抱歉


我一直在研究如何创建解析器,如果可能的话,必须有一个不确定的循环来找到从
T
K
的连接。我不确定C#解析器是否会尝试这样做,但不幸的是,我的钱在“不”上

强制转换不被编译器链接,因此解决问题的方法不起作用

隐式类型转换在类型检查中非常严格。如果编译器知道类型,您的第一个代码段和
测试
类就可以工作:

ValueType<int, Test> t = 6;
Console.WriteLine(t.Value);
ValueType t=6;
控制台写入线(t值);
问题在于,从类型系统的角度来看,
ValueType
,并不总是一个
Test
,因此隐式转换不适用于此


埃里克·利珀特(Eric Lippert)以一种值得一读的方式写了一篇关于这种通用自引用的文章

实现您自己的隐式转换逻辑的规则非常严格,如果您要做这样特别复杂的事情,您应该非常熟悉本规范的第6.4.4节和第10.10.3节

简单地说,您应该了解以下几个关键规则:

  • 定义转换的类型必须出现在用户定义转换的“到”或“从”部分。不能创建定义从E到F转换的类C;C一定在那里的某个地方
  • 永远不可能用自己的隐式转换替换内置的隐式转换;例如,当从C转换为对象时,您不能使特殊行为发生
  • 用户定义的隐式转换将与最多两个内置隐式转换“链接”,但不会与任何其他用户定义的转换“链接”。例如,如果您有一个用户定义的从C到D的隐式转换,以及一个内置的从D到IFoo的隐式转换,那么您就得到了从C到IFoo的隐式转换。但是,如果D有一个用户定义的到E的隐式转换,那么就不能免费获得从C到E的隐式转换
我认为编译器根本不会对强制转换/转换运算符应用隐式链接。。。所以我看不出这有什么意义。还是我遗漏了什么?@Lucero我想知道是否有可能链铸/转换。如果没有,是否有解决方法?如果您将类型系统视为类型图,则不重新访问您在尝试解析类型时已访问过的任何类型(节点),就很容易避免循环上的无限循环。所以这不是原因…;)有趣的Lucero,在你看来,你会使用访问者模式还是在某种地图上记录你访问过的类型?我不喜欢或使用访问者模式,因为它会。也就是说,最简单的方法是将一组访问过的节点作为参数传递,并进行检查,或者使用广度优先的搜索方法,将待处理的节点添加到队列中,如果它们在队列中已经存在,则在退出队列时将其丢弃。我对JavaCC的唯一体验以及它的内置访客支持,我也不太感兴趣!我同意你的第二个想法,这也使得放弃更改变得更容易,对于访问者模式,你必须返回并更改你设置的
bool
!基本上,它归结为将事物视为对象图,而不仅仅是树。树从来没有循环,而图通常有循环,因此,在这种情况下,研究处理图的算法是一种方法。顺便说一句,如果你想在.NET中进行一些解析,你可能想看看-(哦,还有免责声明,我是那篇文章中使用的perser引擎的作者,所以我确实对这个解析器引擎有一些偏见;))。如果定义了从
Func
->
MyClass
的隐式转换,但编译器实际上似乎并没有链接转换,那么这似乎适用于lamba->
Func
->
MyClass
。@NetMage:您能用规范中的引用证明它“应该工作”吗?规范的这一方面是微妙的;仔细阅读。@NetMage:或者,从编译器开发人员的角度考虑。赋值的右侧有一个lambda,左侧有一个类型为
MyClass
的变量
MyClass
具有来自任意多个委托类型的任意多个转换。描述您认为类型推断应该如何从该信息派生lambda的形式参数类型。我想如果你这样做了,你就会明白为什么我没有这样做。我想我发现了我的错误,那就是只有标准隐式转换与用户定义的转换相链接,而标准隐式转换列表(6.3.1)不包括匿名函数转换(6.5)。根据您的问题,现有匿名函数转换不能提供一组兼容的委托类型,用于创建一组可能的用户定义转换,然后应用唯一规则吗?@NetMage:Correct;匿名函数转换不是“标准”。现在,你可能会说,让我们解决这个问题。我们将其视为任何其他过载解决问题;lambda到delegate的转换用于确定运算符的第一个适用性,然后确定是否更好。源表达式需要被视为
ValueType<int, Test> t = 6;
Console.WriteLine(t.Value);