在C#中扩展现有结构以添加运算符

8
我希望扩展.NET内置的Color结构,以添加新的运算符,如+-。 我将使用它们像这样:
Color c1 = Color.FromName("Red");
Color c2 = Color.FromName("Blue");
Color result = c2 - c1;

是否可能?如果是,怎么做呢?


1
我不确定这是否可以完成,但我非常好奇'red - blue'的结果会是什么? - n8wrl
1
@n8wrl:确实很奇怪,但我希望“-”符号可以从另一个RGB值中移除该颜色的任何值。 - Yuck
2
@n8wrl 无论紫色的相反颜色是什么,可能就是那个了 :-) - Adam Houldsworth
1
好的,大家不要再考虑 Color 了,以避免进一步的混淆。毕竟这是一个 C# 的问题 :) 告诉我们是否可以通过运算符扩展现有的结构体。 - Can Poyrazoğlu
@asawyer:你说得对;我们曾考虑在C# 4.0中添加扩展运算符,但最终没有时间和预算。也许在一个假设的未来版本中会加入。 - Eric Lippert
显示剩余4条评论
7个回答

9

使用内置运算符无法完成此操作。

但是,您可以编写扩展方法来模拟它:

public static class Extensions
{
    public static Color Substract(this Color color, Color theOtherColor)
    {
        //perform magic here! 
        //be sure to return something or this won't compile
    }
}

Color c1 = Color.FromName("Red");
Color c2 = Color.FromName("Blue");
Color result = c2.Subtract(c1);

你的语法在定义 Color 的扩展方法时是错误的。必须是一个带有 static 方法的 static 类。 - Yuck
我刚刚注意到我漏掉了“static”修饰符。 - asawyer
1
@asawyer,请删除return nullColor是一个值类型。 - Kirill Polishchuk
@Kirill 好吧,这只是为了表达想法,所以才有关于魔法的评论。 - asawyer

8

正如其他人建议的那样,您可以选择使用扩展方法或装饰器模式。

但是,请考虑到Color具有相当数量的属性和方法,因此将它们全部从装饰器类重定向到包装的Color结构将意味着编写大量样板代码。如果您选择这条路线,确实可以定义运算符甚至是从您的类到Color以及另一个方向的隐式转换(以便更可互换地使用它们),例如:

public class MyColor {
    public System.Drawing.Color val;

    public MyColor(System.Drawing.Color color)
    {
        this.val = color;
    }

    public static MyColor AliceBlue 
    {
        get {
            return new MyColor(System.Drawing.Color.AliceBlue);
        }
    }

    public override string ToString()
    {
        return val.ToString();
    }
    // .... and so on....

    // User-defined conversion from MyColor to Color
    public static implicit operator System.Drawing.Color(MyColor c)
    {
        return c.val;
    }
    //  User-defined conversion from Color to MyColor
    public static implicit operator MyColor(System.Drawing.Color c)
    {
        return new MyColor(c);
    }
}

进行测试:

MyColor c = System.Drawing.Color.AliceBlue; // assigning a Color to a MyColor
                                            // thanks to the implicit conversion
Console.WriteLine(c.ToString()); // writes "Color [AliceBlue]"

这是一个非常好的示例供参考,但在我的当前情况下,它只会让一切变得更加困难。不过代码很棒,隐式操作符在编写代码时真的可以简化事情。 - Can Poyrazoğlu
1
@can poyrazoğlu 我同意。在你的情况下,我个人会使用扩展:我的例子更多是为了向您展示使用“大”结构体(如Color)的另一种方式会变得混乱无比。 - Paolo Falabella

3

C#中的结构体和类有许多相似之处,但其中一个不同之处是你不能对结构体进行子类化。你可以使用扩展方法实现Add() 或Subtract() 方法,但无法在扩展方法中编写操作符重载。

如果我是你,而且我真的想要扩展这种现有结构体的功能,我会将该结构体包装在自己的类中。


+1 在这里使用扩展方法似乎是一个奇怪的地方。 - Yuck

1

我知道扩展方法,但只是想知道是否有使用运算符的可能性。 - Can Poyrazoğlu
请查看 @iandotkelly 的回答。 - Kirill Polishchuk

0
如果您无法扩展某个东西,也可以创建一个包装类或结构体。在许多情况下,组合实际上比扩展更强大和灵活。
它允许多重继承,您可以轻松升级/包装现有对象等。
我并不是说这是对这个问题的最佳答案,但肯定值得考虑。 :)

0

OP所询问的Color对象存在于System.Drawing命名空间中,而不是您所引用的那个。 - Yuck

0

你不能这样做。 有人问能否通过自定义运算符扩展内置的Color结构体。您提供的链接说明如下:(...) 运算符声明必须满足以下规则:(...) 在每种情况下,至少一个参数必须具有T或T?类型,其中T是包含运算符声明的类型。由于您无法将内容放入该内置Color结构的定义中,因此无法向其添加自定义运算符。 正如其他人指出的那样,最接近的方法可能是添加扩展方法,但它不可能是运算符。 - michi-b

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接