我使用一个框架来公开一个名为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的一部分。
答案 0 :(得分:3)
重要的是你不能超越"运营商,因为他们是静态的。您可以在派生类中定义一个新运算符,然后使用派生类型的变量进行赋值(以便编译器知道它需要调用派生类的运算符)。
看看这个例子:
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");
}
}