IT story

C # 확장 메서드를 사용하여 연산자 오버로드

hot-time 2020. 5. 29. 23:44
반응형

C # 확장 메서드를 사용하여 연산자 오버로드


확장 메서드를 사용하여 C # StringBuilder클래스에 연산자 오버로드를 추가하려고합니다 . 특히, 주어진 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는이 문맥에서 허용되지 않습니다.

확장 방법을 통해 연산자 과부하를 추가 할 수 있습니까? 그렇다면 적절한 방법은 무엇입니까?


확장 메서드는 정적 클래스에 있어야하며 정적 클래스에는 연산자 오버로드를 가질 수 없으므로 현재는 불가능합니다.

C # Language PM의 Mads Torgersen은 다음과 같이 말합니다.

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;
  }

} 

The StringBuilderWrapper class declares an implicit conversion operator from a StringBuilder and declares the desired + operator. This way, a StringBuilder can be passed to ReceiveImportantMessage, which will be silently converted to a StringBuilderWrapper, where the + operator can be used.

To make this fact more transparent to callers, you can declare ReceiveImportantMessage as taking a StringBuilder and just use code like this:

  private static void ReceiveImportantMessage(StringBuilder sb) {
    StringBuilderWrapper sbw = sb;
    sbw += "Hello World!";
  }

Or, to use it inline where you're already using a StringBuilder, you can simply do this:

 StringBuilder sb = new StringBuilder();
 StringBuilderWrapper sbw = sb;
 sbw += "Hello World!";
 Console.WriteLine(sb.ToString());

I created a post about using a similar approach to make IComparable more understandable.


It appears this isn't currently possible - there's an open feedback issue requesting this very feature on Microsoft Connect:

http://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=168224

suggesting it might appear in a future release but isn't implemented for the current version.


Though it's not possible to do the operators, you could always just create Add (or Concat), Subtract, and Compare methods....

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;    
        }
    }


}

Hah! I was looking up "extension operator overloading" with exactly the same desire, for sb += (thing).

After reading the answers here (and seeing that the answer is "no"), for my particular needs, I went with an extension method which combines sb.AppendLine and sb.AppendFormat, and looks tidier than either.

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);
    }

}

And so,

sb.Line("the first thing is {0}",first);
sb.Line("the second thing is {0}", second);

Not a general answer, but may be of interest to future seekers looking at this kind of thing.


Its possible to rigg it with a wrapper and extensions but impossible to do it properly. You end with garbage which totally defeats the purpose. I have a post up somewhere on here that does it, but its worthless.

Btw All numeric conversions create garbage in string builder that needs to be fixed. I had to write a wrapper for that which does work and i use it. That is worth perusing.

참고URL : https://stackoverflow.com/questions/172658/operator-overloading-with-c-sharp-extension-methods

반응형