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