2011-04-01 53 views
11

是否可以定义一个扩展方法,同时它是一个运算符? 我想为一个固定的类添加使用实际上无法应用的已知操作符的可能性。 对于这种特殊的情况下,我想这样做:是否可以定义扩展操作符方法?

somestring++; //i really know that this string contains a numeric value 

而且我不希望传播转换类型的所有代码。 我知道我可以在字符串上创建包装类并定义该运算符,但是我想知道这种事情是否可以避免使用MySpecialString搜索并替换每个字符串声明。

编辑:由于大多数人说字符串是密封的,所以派生是不可能的,所以我修改“派生”到“包装”,我的错误。

+0

请参阅本文(http://stackoverflow.com/questions/172658/operator-overloading-with-c-extension-methods/172666#172666)回答: “这目前不可能,因为扩展方法必须在静态类中,静态类不能有运算符重载。“ – rsenna 2011-04-01 20:32:27

+0

:(我看,但因为它是在2008年写的我希望事情已经改变 – mjsr 2011-04-01 20:36:14

回答

4

不,这是不可能从课外做的。 ++运算符应该在正在递增的类中定义。你可以创建自己的类,它可以从字符串转换,并且会有重载,或者你可以忘记这个想法并使用常规方法。

1

目前不支持此功能,因为扩展方法是在单独的静态类中定义的,而静态类不能有运算符重载定义。

8

这在C#中是不可能的,但为什么不是标准的扩展方法?

public static class StringExtensions { 
    public static string Increment(this string s) { 
      .... 
    } 
} 

我觉得somestring.Increment()更是可读的,因为你没有困惑的人谁真的不希望看到++应用于字符串。

+0

感谢您采取的建议。:) – mjsr 2011-04-01 21:12:52

2

该字符串类被密封在C#中,所以创建一个字符串派生类实际上不是可能。这就是说,一个扩展方法当然会工作得很好(如同一个帮助类中的标准静态方法),但它不会是一个运算符,只是通常命名的方法。

5

不,你不能有一个扩展方法,这也是一个操作符。扩展方法只能在静态类中声明,静态类不能有实例,并且根据C#规范,

用户定义的运算符声明始终要求至少有一个参数是类或结构类型包含操作员声明。 [7.3.2]

因此,扩展方法也不可能是一个重载操作符。

此外,您不能覆盖System.String,因为它是sealed类。

1

这都是事实,但M $在未来添加此功能会很好。有时候,框架只是缺少一些东西,而扩展可以帮助缩小差距(或解决问题),有时这可能是运营商。

一个例子。要比较IP地址,您必须使用Equals方法直接进行比较(当然也可以比较单个地址字节的结构部分,但这是另一回事)。但是,使用==运算符总是在对象级别返回false(即,而不会将它们转换为字符串等)。在==运算符调用中放置Equals方法调用有多难(这是修辞),但我们不能这么做。这是不一致的,也是错误蔓延的地方(注意它并不失败,总是等于错误 - 而Equals不等于错误)。

1

我会争辩说,你应该使用一个包装类,即使你可以编写一个扩展操作符应该

//i really know that this string contains a numeric value 

恰恰是类型安全的发明。

查看它的另一种方法是,通过编写该运算符,您已破坏许多其他函数和运算符,它们与string类一起使用,因为它们不一定保留包含数值的属性。通过使用包装类,而不是派生类,您只需重新实现string对数字字符串有意义的那些功能。

5

一个明确的例子,这将是有用的是能够扩展TimeSpan类包括*和/运营商。

这是在理想情况下工作...

public static class TimeSpanHelper 
{ 
    public static TimeSpan operator *(TimeSpan span, double factor) 
    { 
     return TimeSpan.FromMilliseconds(span.TotalMilliseconds * factor); 
    } 

    public static TimeSpan operator *(double factor, TimeSpan span) // * is commutative 
    { 
     return TimeSpan.FromMilliseconds(span.TotalMilliseconds * factor); 
    } 

    public static TimeSpan operator /(TimeSpan span, double sections) 
    { 
     return TimeSpan.FromMilliseconds(span.TotalMilliseconds/factor); 
    } 

    public static double operator /(TimeSpan span, TimeSpan period) 
    { 
     return span.TotalMilliseconds/period.TotalMilliseconds); 
    } 

} 
+1

确实。做很多.Multiply().Divide()等等的时间跨度数学很快就变得丑陋了 – 2015-02-19 23:40:36

+0

我尝试并得到“静态类不能包含用户定义的运算符”,如果它不是静态的,那么我得到“二元运算符的一个参数超载应该是包含类型的“ – Felype 2016-08-19 13:59:28

0

我是在一个非常类似的情况。像你描述:我需要提高的文本(包含一定数值)Windows窗体的文本框。

我理解像你描述

somestring ++您的需要; //我真的知道,这个字符串包含一个数值

我soultion是类似的东西,我认为这是接近你的描述

somestring =(递增的)somestring + 1

所有我需要做的是

  1. 创建类称为incrementable
  2. 限定在它的一个明确的操作者(以有助于转换stringincrementable
  3. 限定在它的隐式操作(以有助于转换incrementablestring
  4. 操作者+(加号)

以下是我的班级看起来如何完整

public class incrementable 
{ 
    public string s; // For storing string value that holds the number 

    public incrementable(string _s) 
    { 
     s = _s; 
    } 

    public static explicit operator incrementable(string tmp) 
    { 
     return new incrementable(tmp); 
    } 

    public static implicit operator string(incrementable tmp) 
    { 
     return tmp.s; 
    } 

    public static incrementable operator +(incrementable str, int inc) // This will work flawlessly like `somestring = (incrementable)somestring + 1` 
     => new incrementable((Convert.ToInt32(str.s) + inc).ToString()); 

    public static incrementable operator ++(incrementable str) // Unfortunately won't work, see below 
     => new incrementable((Convert.ToInt32(str.s) + 1).ToString()); 
} 

不幸的是,我只是无法管理我通过使用一元运算符++来改善我的课程。使用像((incrementable)somestring)++这样的隐式转换的原因在于它会导致错误,说The operand of an increment or decrement operator must be a variable, property or indexer因此不能是该转换的结果。

无论如何,希望这有助于!

相关问题