【问题标题】:Overriding implicit operators in C#覆盖 C# 中的隐式运算符
【发布时间】:2017-09-13 07:01:08
【问题描述】:

我使用了一个框架,它公开了一个名为Value 的抽象类。通过运算符重载,几乎可以将任何东西分配给这个类的对象,它就像一个魅力:

Value a = "hello";
Value b = 1;
Value c = true;
Value d = 3.14;

(请注意,这是创建Value 实例的唯一方法。除了重载的运算符之外,没有公共/受保护的方法可以为实例赋值。)

现在,我想重写 implicit operator Value(string input) 函数,以便在分配之前对任何字符串进行 XML 过滤。

我已经尝试过继承这个类并覆盖操作符,但还没有找到一种方法将净化后的字符串提供给基类​​的操作符函数。以下显然不起作用:

public override static implicit operator XmlValue(string input)
{
    string output = sanitize(input);
    XmlValue rv = null;
    ((Value)rv) = output; // this is not possible
    return rv;
}

有没有办法做到这一点?或者,我是否可能过度思考了这个问题,是否有更好的解决方案来解决我想做的事情?在任何情况下,我都希望避免在将每个字符串分配给Value 之前对其进行清理;这太容易出错了。

仅供参考:Value 类是 Cottle framework 的一部分。

【问题讨论】:

    标签: c# operator-overloading overriding


    【解决方案1】:

    重要的一点是您不能“覆盖”运算符,因为它们是静态的。您可以改为在派生类中定义一个新运算符,然后使用派生类型的变量进行赋值(以便编译器知道它需要调用派生类的运算符)。

    看这个例子:

    using System;
    
    class Value {
        public string StringValue {
            get;
            private set;
        }
        protected Value(string str) {
            StringValue = str;
        }
        public static implicit operator Value(string input) {
            return new Value(input);
        }
    }
    
    class XmlValue : Value {
        protected XmlValue(string str) : base(str) {
        }
        public static implicit operator XmlValue(string input) {
            // using "ToUpperInvariant" instead of sanitize
            return new XmlValue(input.ToUpperInvariant());
        }
    }
    
    class Program {
        static void Main(string[] args) {
            Value v1 = "test";
            Console.WriteLine(v1.StringValue); // "test"
            XmlValue v2 = "test";
            Console.WriteLine(v2.StringValue); // "TEST"
        }
    }
    

    查看您的评论,我认为下面的例子更贴近您所面临的实际情况。

    但是,尽管这种运算符重载可能很有趣,但我认为在这种情况下,您绝对应该选择更简单、更易读的解决方案,即在分配之前对每个输入进行清理。

    using System;
    
    abstract class Value {
        public string StringValue {
            get;
            protected set;
        }
        public static implicit operator Value(string input) {
            return new StringValue(input);
        }
    }
    
    class StringValue : Value {
        public StringValue(string str) {
            StringValue = str;
        }
    }
    
    class Xml {
        string _value;
        public Xml(string value) {
            _value = value;
        }
        public static implicit operator Xml(string input) {
            return new Xml(input.ToUpperInvariant());
        }
        public static implicit operator Value(Xml xml) {
            Value ret = xml._value;
            return ret;
        }
    }
    
    class Program {
        static void Main(string[] args) {
            // this works with the cast operators...
            Value v1 = (Xml)"test";
            Console.WriteLine(v1.StringValue); // "TEST"
    
            // ...but I would definitely go for this:
            Value v2 = sanitize("test");
        }
    }
    

    【讨论】:

    • 由于Value 没有受保护/公共的构造函数或设置器,我认为这是不可能的。
    • @LeeWhite:那么你是如何声明你的XmlValue 类的?我假设它是一个派生类...
    • 它是一个派生类,声明为abstract public class XmlValue : Value。它被声明为抽象的。由于Value 也是抽象的,这允许我只覆盖这个特定的方法,而不必实现所有的抽象方法。我应该在原始问题中包含这些内容吗?
    • @LeeWhite:提供一个有助于理解类层次结构如何工作的最小示例会很有用。我现在无法调查 Cottle 框架...
    • @LeeWhite:我做了第二个例子,应该更类似于你的真实用例......
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多