我正在尝试使用扩展方法向C#StringBuilder
类添加一个operater重载.具体来说,给定StringBuilder
sb
,我想sb += "text"
成为等同于sb.Append("text")
.
以下是为以下内容创建扩展方法的语法StringBuilder
:
public static class sbExtensions { public static StringBuilder blah(this StringBuilder sb) { return sb; } }
它成功地将blah
扩展方法添加到了StringBuilder
.
不幸的是,运算符重载似乎不起作用:
public static class sbExtensions { public static StringBuilder operator +(this StringBuilder sb, string s) { return sb.Append(s); } }
除其他问题外,this
在此上下文中不允许使用关键字.
是否可以通过扩展方法添加运算符重载?如果是这样,那么正确的方法是什么?
目前这是不可能的,因为扩展方法必须是静态类,静态类不能有操作符重载.
Mads Torgersen,C#语言PM说:
...对于Orcas版本,我们决定采取谨慎的方法,只添加常规扩展方法,而不是扩展属性,事件,运算符,静态方法等.常规扩展方法是我们LINQ所需要的,他们有一种语法上最小的设计,对于某些其他成员类型来说,这些设计无法轻易模仿.
我们越来越意识到其他类型的扩展成员可能会有用,因此我们将在Orcas之后回到这个问题.不过没有保证!
编辑:
我刚才注意到,Mads在同一篇文章中写道:
很抱歉,我们不会在下一个版本中这样做.我们确实在我们的计划中非常认真地对待扩展成员,并且花费了大量精力来努力使它们正确,但最终我们无法让它变得平滑,并决定让位于其他有趣的功能.
对于未来的版本,这仍然是我们的关注点.如果我们获得了大量有助于推动正确设计的引人注目的场景,那将会有什么帮助.
此功能目前(可能)用于C#8.0.Mads谈到了在这里实施它的更多信息.
如果您控制要使用此"扩展操作符"的位置(通常使用扩展方法),您可以执行以下操作:
class Program { static void Main(string[] args) { StringBuilder sb = new StringBuilder(); ReceiveImportantMessage(sb); Console.WriteLine(sb.ToString()); } // the important thing is to use StringBuilderWrapper! private static void ReceiveImportantMessage(StringBuilderWrapper sb) { sb += "Hello World!"; } } public class StringBuilderWrapper { public StringBuilderWrapper(StringBuilder sb) { StringBuilder = sb; } public StringBuilder StringBuilder { get; private set; } public static implicit operator StringBuilderWrapper(StringBuilder sb) { return new StringBuilderWrapper(sb); } public static StringBuilderWrapper operator +(StringBuilderWrapper sbw, string s) { sbw.StringBuilder.Append(s); return sbw; } }
的StringBuilderWrapper
类声明的隐式转换运算符从一个StringBuilder
和声明了期望的+
运算符.通过这种方式,StringBuilder
可以传递给a ReceiveImportantMessage
,它将被静默转换为a StringBuilderWrapper
,+
可以使用运算符.
为了使这个事实对调用者更透明,你可以声明ReceiveImportantMessage
为a StringBuilder
并使用如下代码:
private static void ReceiveImportantMessage(StringBuilder sb) { StringBuilderWrapper sbw = sb; sbw += "Hello World!"; }
或者,要在内联使用它的地方使用它StringBuilder
,您可以简单地执行此操作:
StringBuilder sb = new StringBuilder(); StringBuilderWrapper sbw = sb; sbw += "Hello World!"; Console.WriteLine(sb.ToString());
我创建了一篇关于使用类似方法使其IComparable
更易理解的帖子.
目前看来这是不可能的 - 在Microsoft Connect上有一个开放的反馈问题请求这个功能:
http://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=168224
建议它可能出现在将来的版本中,但不会针对当前版本实现.