简体   繁体   English

在通用 c# 类中链接隐式运算符

[英]Chaining implicit operators in generic c# classes

For the following generic c# class, I'd like to convert T to K:对于以下通用 c# class,我想将 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;    
    }
}

If I were to implement a direct operator implicit operator K(T val) it would result in a compile-time error (CS0556).如果我要实现直接运算符implicit operator K(T val) ,它将导致编译时错误 (CS0556)。

I thought I could try chaining implicit operators:我想我可以尝试链接隐式运算符:

public static implicit operator K(ValueType<T,K> vt){
    return (K)val;
}

but the following example still complains that it can't be converted:但是下面的例子仍然抱怨无法转换:

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);

I really want to avoid explicitly casting if possible.如果可能的话,我真的想避免显式转换。

This question extends upon another SO question I've previously raised.这个问题延伸到我之前提出的另一个 SO 问题

The rules for implementing your own implicit conversion logic are quite strict and you should probably become very familiar with sections 6.4.4 and 10.10.3 of the specification if you're going to do particularly complicated ones like this. 实现自己的隐式转换逻辑的规则非常严格,如果您要进行此类特别复杂的操作,则应该熟悉本规范的6.4.4和10.10.3节。

Briefly, a few key rules you should know are: 简要地说,您应该了解一些关键规则:

  • The type that you are defining the conversion in has to appear in either the "to" or "from" portion of the user-defined conversion. 您定义转换所用的类型必须出现在用户定义的转换的“到”或“从”部分中。 You can't make a class C that defines a conversion from E to F; 您不能创建定义从E到F的转换的C类; C has got to be in there somewhere. C必须在某个地方。
  • It is never possible to replace a built-in implicit conversion with one of your own; 永远不可能用您自己的一个替换内置的隐式转换。 you can't make special behaviour happen when converting from C to object, for example. 例如,当您从C转换为对象时,就无法发生特殊行为。
  • User-defined implicit conversions will be "chained" with up to two built-in implicit conversions, but not with any other user-defined conversions. 用户定义的隐式转换将与最多两个内置的隐式转换“链接”,但不能与任何其他用户定义的转换“链接”。 So for example, if you have a user-defined implicit conversion from C to D, and a built-in implicit conversion from D to IFoo, then you get an implicit conversion from C to IFoo. 因此,例如,如果您具有从C到D的用户定义的隐式转换,以及从D到IFoo的内置隐式转换,那么您将获得从C到IFoo的隐式转换。 But if D has a user-defined implicit conversion to E, then you don't get an implicit conversion from C to E for free. 但是,如果D具有用户定义的到E的隐式转换,那么您就不会免费获得从C到E的隐式转换。

Casts are not chained by the compiler, so that way of solving the issue doesn't work. 强制转换未通过编译器链接,因此无法解决问题。

Implicit casts are quite strict in the type checking. 隐式转换在类型检查中非常严格。 Your very first snippet and the Test class do work if the compiler knows the type: 如果编译器知道类型,则第一个代码段和Test都可以工作:

ValueType<int, Test> t = 6;
Console.WriteLine(t.Value);

The problem is that your ValueType<int, Test> - from the type system point of view - is not always a Test , so that the implicit conversion doesn't apply there. 问题是,从类型系统的角度来看,您的ValueType<int, Test>并不总是Test ,因此隐式转换不适用于该类。

Eric Lippert wrote a blog post on this kind of generic self-referencing by the way - worth a read! 埃里克·利珀特(Eric Lippert)撰写了一篇有关这种通用自引用的博客文章 -值得一读!

As far as I know, I don't think that you can chain casts together, sorry about that. 据我所知,我认为您不能将演员表捆绑在一起,对此感到抱歉。

I've been studying how to create parsers, and if this was possible, there would have to be an indefinite loop to find the connection from T to K . 我一直在研究如何创建解析器,如果可能的话,必须存在一个不确定的循环才能找到从TK的连接。 I'm not sure that the C# parser would try doing that, but my money is on no, unfortunately! 我不确定C#解析器是否会尝试这样做,但是不幸的是,我的钱没有用!

Here is what I came up to.这是我想到的。 Not an answer to the OP question, but as far as I look for, from C# rules it is not possible anyway.不是 OP 问题的答案,但据我所知,从 C# 规则来看,无论如何都是不可能的。 So what I did it to implement the implicit operator in concrete class that rely on the conversion algorithm defined in the abstract class.所以我做了什么来实现具体 class 中的隐式运算符,它依赖于抽象 class 中定义的转换算法。

My classes:我的课程:

public interface IInjectable<T>
{
    T Value { get; set; }
}

internal abstract class Injectable<T,P> : IInjectable<T>
    where P : Injectable<T,P>, new()
{
    public abstract T Value { get; set; }

    public static implicit operator T(Injectable<T,P> injectable) => injectable.Value;
    
    //public static implicit operator Injectable<T,P>(T value) => new P { Value = value };
    public static P Convert(T value) => new P { Value = value };        
}

internal class InjectableGuid : Injectable<Guid, InjectableGuid>
{
    public override Guid Value { get; set; } = Guid.Empty;

    public override string ToString() => Value.ToString();        

    public static implicit operator InjectableGuid(Guid guid) => Convert(guid);        
}

Usage:用法:

Guid id = new InjectableGuid();
Console.WriteLine(id.ToString());

Guid newId = Guid.NewGuid();
Console.WriteLine("Guid.ToString() : "+newId.ToString());
InjectableGuid injected = newId;
Console.WriteLine("InjectableGuid.ToString() : "+injected.ToString());

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM