C #에서 대괄호 연산자를 어떻게 과부하합니까?


254

예를 들어 DataGridView를 사용하면 다음을 수행 할 수 있습니다.

DataGridView dgv = ...;
DataGridViewCell cell = dgv[1,5];

그러나 내 인생에서 색인 / 대괄호 연산자에 대한 문서를 찾을 수 없습니다. 그들은 그것을 무엇이라고 부릅니까? 어디에서 구현됩니까? 던질 수 있습니까? 내 수업에서 어떻게 똑같은 일을 할 수 있습니까?

ETA : 모든 빠른 답변에 감사드립니다. 간단히 : 관련 문서는 "항목"속성에 있습니다. 오버로드하는 방법은 다음과 같은 속성을 선언하는 것입니다 public object this[int x, int y]{ get{...}; set{...} }. 적어도 문서에 따르면 DataGridView의 인덱서는 throw되지 않습니다. 유효하지 않은 좌표를 제공하면 어떻게되는지 언급하지 않습니다.

ETA 다시 : OK, 문서에서 언급하지 않았지만 (Microsoft가 아닙니다!) 잘못된 좌표를 제공하면 DataGridView의 인덱서에서 ArgumentOutOfRangeException이 발생합니다. 공정한 경고.

답변:


374

여기에서 방법을 찾을 수 있습니다 . 간단히 말해 :

public object this[int i]
{
    get { return InnerList[i]; }
    set { InnerList[i] = value; }
}

게터 만 필요한 경우 아래 답변 의 구문을 사용할 수도 있습니다 (C # 6부터).


9
사소한 의견 :하고있는 일에 따라 다음과 같이하는 것이 더 적절할 수 있습니다. get {return base [i]; } set {base [i] = 값; }
MikeBaz

7
이것은 연산자 오버로드가 아닙니다.
소멸자

5
인덱서는 단항 연산자 일 수도 있습니다.
alan2here

1
2019 년, 새 응답이 선택해야 이 하나 . 너무 나쁜 SO는 새로운 답변이 350 + 이상 투표를받을 수는 없지만 더 이상 사용되지 않는 답변을 처리 할 수있는 기능이 없습니다.

@ mins 다른 답변에 대한 링크를 포함 시켰습니다.
Ruben

41

이것이 항목 속성이 될 것입니다 : http://msdn.microsoft.com/en-us/library/0ebtbkkc.aspx

아마도 이런 식으로 작동 할 것입니다 :

public T Item[int index, int y]
{ 
    //Then do whatever you need to return/set here.
    get; set; 
}

고마워요! 두 가지 답변을 할 수 있다면, 당신도 추가 할 것입니다. 아무도 문서에서 항목을 찾을 줄 몰랐습니다 ...
Coderer

5
구현 방법에 대해서는 "Item"이지만 C #에서는 "this"입니다
Marc Gravell

1
맞다. 그러나 나는 "나의 생애 동안 인덱스 / 대괄호 연산자에 대한 문서를 찾을 수 없다"고 물었다. 나는 MSDN에서 라이브러리 클래스를 찾을 때 연산자에 대해 어디에서 말 했는가? 이것이 내가 던지는 것에 대해 마지막 "ETA"를 만든 이유 입니다. 문서가 잘못되었습니다 .
Coderer

26
Operators                           Overloadability

+, -, *, /, %, &, |, <<, >>         All C# binary operators can be overloaded.

+, -, !,  ~, ++, --, true, false    All C# unary operators can be overloaded.

==, !=, <, >, <= , >=               All relational operators can be overloaded, 
                                    but only as pairs.

&&, ||                  They can't be overloaded

() (Conversion operator)        They can't be overloaded

+=, -=, *=, /=, %=                  These compound assignment operators can be 
                                    overloaded. But in C#, these operators are
                                    automatically overloaded when the respective
                                    binary operator is overloaded.

=, . , ?:, ->, new, is, as, sizeof  These operators can't be overloaded

    [ ]                             Can be overloaded but not always!

정보 출처

브래킷의 경우 :

public Object this[int index]
{

}

그러나

배열 인덱싱 연산자 는 오버로드 될 수 없습니다 . 그러나 형식은 인덱서, 하나 이상의 매개 변수를 사용하는 속성을 정의 할 수 있습니다. 인덱서 매개 변수는 배열 인덱스와 마찬가지로 대괄호로 묶지 만 인덱서 매개 변수는 배열 인덱스와 달리 모든 유형으로 선언 할 수 있습니다 (배수 형이어야 함).

에서 MSDN


예 그것은, 오버로드 할 수 한 매개 변수 서명이 정확히 어떤 다른 방법의 과부하 제한과 같은 다른로
찰스 Bretana

내가 쓴 조건으로는 할 수는 없지만 할 수는 없습니다. MSDN에서 온 것입니다. 당신이 나를 믿지 않으면 소스를 확인하십시오
Patrick Desjardins

1
게시물을 잘못 읽은 경우 죄송하지만 어떤 조건을 언급하고 있습니까?
찰스 브레 타나

편리한 목록은 +1입니다. 참고로 링크가 죽었습니다. (4 년 후, 나는 알고있다)
Mixxiphoid

C #에서 암시 적 및 명시 적 유형 캐스팅을 모두 무시할 수 있다고 덧붙이고 싶습니다.
Felype

9

C # 6 이상을 사용하는 경우 get-only indexer에 표현식 본문 구문을 사용할 수 있습니다.

public object this[int i] => this.InnerList[i];


6
public class CustomCollection : List<Object>
{
    public Object this[int index]
    {
        // ...
    }
}

5
실제로 이것은 매우 위험합니다. 이제 List <T> 또는 IList <T> 또는 IList 등으로 유형이 지정된 변수를 가진 사람은 사용자 지정 코드를 실행하지 않는 두 가지 경쟁 구현이 있습니다.
Marc Gravell

1
합의 - 아무것도, 그것은 목록에서하여 CustomCollection를 도출 할 필요가 없습니다,하지만 내가 실현하지 않았다면 실제로 위험한
Coderer

그래도 여전히 커스텀 코드를 실행하지 않습니까? 선언하는 변수 유형은 중요하지 않습니다. 중요한 것은 개체의 유형입니다.
izb

1
C # 다형성에 대한 친근한 알림 : 기본 클래스가 구현을 가상으로 선언하지 않기 때문에 발생합니다. 가상으로 선언 된 경우 모든 경우에 사용자 지정 코드가 호출됩니다.
almulo

1
또한이 코드는 두 인덱서 모두 가상이 아니므로 컴파일러 경고를 표시합니다. 컴파일러는 new키워드로 사용자 정의 색인 작성기를 규정 할 것을 제안합니다 .
amoss

4

/ clr로 컴파일 된 CLI C ++에 대해서는 이 MSDN 링크를 참조하십시오 .

간단히 말해, 속성에 "default"라는 이름을 지정할 수 있습니다.

ref class Class
{
 public:
  property System::String^ default[int i]
  {
    System::String^ get(int i) { return "hello world"; }
  }
};

2

다음은 내부 List 객체에서 값을 반환하는 예입니다. 당신에게 아이디어를 제공해야합니다.

  public object this[int index]
  {
     get { return ( List[index] ); }
     set { List[index] = value; }
  }

1

배열 인덱서를 의미하는 경우 인덱서 속성을 작성하여 오버로드 할 수 있습니다. 인덱서 속성이 서로 다른 매개 변수 서명이있는 한 인덱서 속성을 오버로드 (원하는만큼 작성) 할 수 있습니다.

public class EmployeeCollection: List<Employee>
{
    public Employee this[int employeeId]
    {   
        get 
        { 
            foreach(var emp in this)
            {
                if (emp.EmployeeId == employeeId)
                    return emp;
            }

            return null;
        }
    }

    public Employee this[string employeeName]
    {   
        get 
        { 
            foreach(var emp in this)
            {
                if (emp.Name == employeeName)
                    return emp;
            }

            return null;
        }
    }
}

2
먼저 this ()가 아니라 this []를 의미합니다. 그러나 목록 (IList / IList <T> / List <T>)에 사용자 정의 (그러나 다른) this [int]를 제공하는 것은 매우 위험합니다. "int index"와 "int employeeId"버전 사이에 미묘한 버그가 발생할 수 있습니다. 둘 다 여전히 호출 가능합니다.
Marc Gravell

그리고 실제로, 나는 위에서 입력 한 코드가 this [int]의 List <T> 구현의 존재로 인해 새로운 문장이나 재정의 명령문을 정확하게 추가하지 않고 컴파일되지 않을 것이라고 생각합니다. 이 작업을 수행 할 때의 잠재력에 대해 옳았습니다. 인덱서 오버로드의 예입니다.
Charles Bretana
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.