简体   繁体   中英

Overriding implicit operators in C#

I use a framework which exposes an abstract class called Value . Through operator overloading, it's possible to assign almost anything to this class's objects, and it works like a charm:

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

(Note that this is the only way to create instances of Value . There are no public/protected ways to assign values to instances, other than the overloaded operators.)

Right now, I want to override the implicit operator Value(string input) function, so that it XML-sanitizes any string before assigning it.

I have tried inheriting this class and overriding the operator, but have not found a way to feed the sanitized string into the base class's operator function. The following obviously doesn't work:

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

Is there a way to achieve this? Or alternatively, am I perhaps overthinking the problem and is there a better solution for what I want to do? In any case, I'd like to avoid having to sanitize each and every string before assigning it to a Value ; this would be way too error prone.

FYI: the Value class is part of the Cottle framework .

The important point is that you cannot "override" operators, because they are static. You can instead define a new operator in your derived class, then make the assignment using a variable of your derived type (so that the compiler knows that it needs to call the operator of the derived class).

Look at this example:

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"
    }
}

After checking your comment , I think that the example below is more related to the real situation you are facing.

However, as fun as this operators overloading might be, I think that in this case you should definitely opt for the simpler and more readable solution of sanitizing every input before assignment.

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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