2010-04-06 5 views
7

G'Day 메이트 과부하 -C# 문자열 연산자

문자열 연산자를 오버로드하는 (이 좋습니다 여부에 인수 제외) 올바른 방법은 무엇입니까 <,>, < = 및> =?

일요일까지 5 가지 방법을 시도했지만 다양한 오류가 발생했습니다. 내 최고의 샷은 부분 클래스를 선언하고 거기에서 오버로드되는 것이지만 어떤 이유로 작동하지 않습니다.

namespace System 
{ 
    public partial class String 
    { 
     public static Boolean operator <(String a, String b) 
     { 
      return a.CompareTo(b) < 0; 
     } 

     public static Boolean operator >(String a, String b) 
     { 
      return a.CompareTo(b) > 0; 
     } 
    } 

}

+0

FYI : 부분 클래스가 동일한 어셈블리 (프로젝트)에 있어야합니다. –

+0

이러한 연산자는 문자열에 대해 이미 정의되어 있으므로 다시 정의하는 것이 바람직하지 않습니다. 가능하다면 많은 코드를 망칠 수 있습니다. – Phil1970

답변

16

문자열은 봉인 된 클래스입니다. 상속받을 수 없으며 String의 원본 ​​소스가 없으면 부분 클래스를 컴파일 할 수 없습니다. 리플렉터 나 비주얼 스튜디오 심볼 다운로드를 통해 소스에 손을 뻗어 두었을지라도, 런타임에서 가장 우선적 인 시민이기 때문에 여전히 문제가있을 수 있습니다.

문자열에 연산자로 <과>가 정말로 필요합니까? 그렇다면 ... extension methods을 사용하지 않는 이유는 무엇입니까?

public static bool IsLessThan(this string a, string b) 
{ 
    return a.CompareTo(b) < 0; 
} 

public static bool IsGreaterThan(this string a, string b) 
{ 
    return a.CompareTo(b) > 0; 
} 


// elsewhere... 
foo.IsLessThan(bar); // equivalent to foo < bar 
+4

그가 상속받을 수있는 경우에도 상속 된 유형 ** 인 인스턴스와 상속 된 유형 **으로 참조 된 인스턴스 만 대체 연산자를 사용할 수 있습니다. 연산자는 다형성이 아니기 때문에 (오버로드되지 않고 오버라이드되지 않음) 하위 유형을 '문자열'로 참조하는 경우에도 대체 연산자 기능이 제거됩니다. –

+0

@Adam Robinson : 정확하게. 결론 : @ScottSEA는 단순히 그가하고 싶은 일을 할 수 없습니다. – Randolpho

+1

귀하의 게시물은 확장 방법이 아니라 링크를 제공하는 것이 유용 할 수 있습니다. C#에 익숙하지 않은 누군가에게는 잘못되었다고 생각됩니다. http://msdn.microsoft.com/en-ca/library/vstudio/bb383977.aspx – jgreep

5

당신이 System.String 클래스를 의미합니까? 그것은 C#에서는 불가능합니다. 기존 클래스에 확장 연산자를 추가 할 수 없습니다. 그것은 많은 요청 기능입니다.

10

간단한 대답은 할 수 없다는 것입니다. 다른 클래스의 연산자를 수정할 방법이 없습니다. 부분 클래스는 이 모든 파일에서 partial으로 선언 된 클래스에만 허용됩니다.은 동일한 어셈블리에 정의되어 있습니다. 문자열 클래스 자체가 partial 클래스 작동하지 않습니다 따라서하지 부분하고 있기 때문에

3
  • 당신은, 문자열에 대한 부분 클래스를 가질 수 없습니다.

  • 문자열이 봉인되어 있으므로 문자열을 상속하고 연산자에 과부하가 걸릴 수 있습니다. 한마디로

는, 슬프게도, 당신은 무엇을 당신이 수행하는 함께하지 수 있습니다.

정확히 무엇을 하려는지 알 수 없으므로 좋은 대안을 제안 할 수 없습니다. 그러나 종종 상황에 좋은 extension methods을 살펴보십시오. 이든 :)이든간에 문자열 클래스에 IsGreaterThan이라는 메서드를 추가하여 원하는대로 true 또는 false를 반환 할 수 있습니다. 이것은 확장 메소드에 명확한 의미를 부여하고, 기존 연산자를 그대로 유지하며 (어쨌든 선택의 여지가없는) 이름을 부여 할 수 있고 빠르고 간단한 코드를 허용하기 때문에 좋습니다.

1

=> 및 < = 연산자를 직접 오버로드 할 수는 없지만> 및 ==을 별도로 오버로드하여 동일한 결과를 얻을 수 있습니다.

==에 대한 오버로드를 놓친 사실을 제외하고 코드가 정확하다고 생각됩니다.

내가 잘못 생각한 것처럼 보였지만, 언제나 리플렉션으로 돌아갈 수 있습니다. 파고들과 해킹을한다면 리플렉션이 함수를 추가하거나 런타임에 함수 바디를 스왑 할 수 있기 때문에 리플렉션을 사용하여 클래스를 확장 할 수 있다고 생각합니다.

권장 사항인지 여부는 상관 없습니다. 클래스가 봉인 된 이유가 있습니다. 내가 언급 한 일을하는 것은 .net 프레임 워크가 문자열에 대해 내린 가정 때문에 일부 상황에서는 정의되지 않은 동작을 초래할 수 있습니다. 문자열 클래스가 내부적으로 축소 될 가능성이 큽니다.

+1

나쁜 연습 때문에 Downvote? : p – Henri

15

기본 제공 컴파일러의 동작을 자신의 것으로 바꿀 방법이 없습니다. 비교, 변환, 산술 등 기존 내장 연산자를 재정의 할 수 없습니다. 그건 의도적으로입니다. 누군가가 여러분의 코드를 읽을 수 있고, int x = M(); int y = x + 2;은 하드 디스크의 포맷팅과는 달리 정수 산술 연산을 수행합니다.

이유를 설명 할 수 있습니까? 아마도 당신이 원하는 것을 할 수있는 더 좋은 방법이있을 것입니다.

+0

그 해답을 보내 주셔서 감사합니다. 디자인 결정을 철저하게 준수하면서 10 년 전 사용자 지정 문자열 연산자를 사용할 수 없었던 이유를 설명 할 수 있습니다. –

+0

내가 무엇을 찾고있을 것이다하는 것은 표현하기보다는이다 'String.Concat (Enumerable.Repeat ("안녕하세요", 4))' 로 ' "안녕하세요"* 그게 가능하다면 4' 아무도 알고 있나요 어떠한 방식으로? –

+1

@AlexeyKhoroshikh : 아니요. 해당 연산자를 정의 할 수있는 유형이 없습니다. –