我正在尝试使用扩展方法向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
。
是否可以通过扩展方法添加运算符重载?如果是这样,那么正确的方法是什么?
答案 0 :(得分:144)
目前这不可能,因为扩展方法必须在静态类中,而静态类不能有操作符重载。
Mads Torgersen,C#语言PM说:
...对于Orcas的发布,我们决定 采取谨慎的方法并添加 只有常规的扩展方法,如 反对延伸财产, 事件,运算符,静态方法等 等常规扩展方法 我们需要LINQ,他们有 一种语法上最小的设计 一些人不可能轻易模仿 其他成员的种类。
我们越来越意识到了 其他类型的扩展成员 可能有用,所以我们会回来 在Orcas之后的这个问题。没有 但保证!
编辑:
我刚注意到,Mads在same article中写了更多内容:
我很遗憾地报告说我们不会 在下一个版本中这样做。我们 确实非常接受扩展会员 认真地在我们的计划中,花了一个 我们付出了很多努力 对,但最终我们无法得到 它足够顺利,并决定给予 其他有趣的功能。
这仍然是我们未来的关注点 版本。如果我们得到了什么会有所帮助 大量引人注目的场景 这有助于推动正确的设计。
This feature is currently on the table (potentially) for C# 8.0. Mads更多地谈论实施它here。
答案 1 :(得分:54)
如果你控制你想要使用这个“扩展操作符”的地方(你通常使用扩展方法),你可以这样做:
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
的implicit conversion operator,声明所需的+
运算符。这样,StringBuilder
就可以传递给ReceiveImportantMessage
,StringBuilderWrapper
会以静默方式转换为+
,可以使用ReceiveImportantMessage
运算符。
为了使这一事实对来电者更加透明,您可以将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
我创建a post关于使用类似的方法使{{1}}更容易理解。
答案 2 :(得分:8)
目前看来这是不可能的 - 在Microsoft Connect上有一个开放的反馈问题请求这个功能:
http://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=168224
建议它可能出现在将来的版本中,但不会针对当前版本实现。
答案 3 :(得分:1)
虽然不可能做操作符,但你总是可以创建Add(或Concat),Subtract和Compare方法....
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Whatever.Test
{
public static class Extensions
{
public static int Compare(this MyObject t1, MyObject t2)
{
if(t1.SomeValueField < t2.SomeValueField )
return -1;
else if (t1.SomeValueField > t2.SomeValueField )
{
return 1;
}
else
{
return 0;
}
}
public static MyObject Add(this MyObject t1, MyObject t2)
{
var newObject = new MyObject();
//do something
return newObject;
}
public static MyObject Subtract(this MyObject t1, MyObject t2)
{
var newObject= new MyObject();
//do something
return newObject;
}
}
}
答案 4 :(得分:0)
哈!我正在查找&#34;扩展运算符重载&#34; sb + =(thing)。具有完全相同的愿望。
在这里阅读答案(并且看到答案是&#34;没有&#34;),为了我的特殊需要,我选择了一个结合了sb.AppendLine和sb.AppendFormat的扩展方法,看起来比任
public static class SomeExtensions
{
public static void Line(this StringBuilder sb, string format, params object[] args)
{
string s = String.Format(format + "\n", args);
sb.Append(s);
}
}
所以,
sb.Line("the first thing is {0}",first);
sb.Line("the second thing is {0}", second);
不是一般性答案,但未来寻求此类事情的求职者可能会感兴趣。
答案 5 :(得分:0)
可以使用包装器和扩展来绑定它,但不能正确地完成它。你以垃圾结束,这完全违背了目的。 我在这里的某个地方有一个帖子可以做到,但它毫无价值。
顺便说一下 所有数字转换都在字符串构建器中创建需要修复的垃圾。我必须编写一个包装器,它可以工作并使用它。这值得细读。