ฉันจะโอเวอร์โหลดตัวดำเนินการตัวยึดสี่เหลี่ยมใน C # ได้อย่างไร


254

ตัวอย่างเช่น DataGridView ให้คุณทำสิ่งนี้:

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

แต่สำหรับชีวิตของฉันฉันไม่พบเอกสารในตัวดำเนินการ index / square-bracket พวกเขาเรียกว่าอะไร มันใช้งานที่ไหน มันโยนได้มั้ย ฉันจะทำสิ่งเดียวกันในชั้นเรียนของตัวเองได้อย่างไร

การทางพิเศษแห่งประเทศไทย: ขอบคุณสำหรับคำตอบอย่างรวดเร็วทั้งหมด สั้น ๆ : เอกสารที่เกี่ยวข้องอยู่ภายใต้คุณสมบัติ "รายการ" วิธีในการโอเวอร์โหลดคือการประกาศคุณสมบัติเช่นpublic object this[int x, int y]{ get{...}; set{...} }; ตัวสร้างดัชนีสำหรับ DataGridView ไม่ส่งอย่างน้อยตามเอกสาร ไม่ได้พูดถึงสิ่งที่เกิดขึ้นหากคุณให้พิกัดที่ไม่ถูกต้อง

การทางพิเศษแห่งประเทศไทยอีกครั้ง: ตกลงแม้ว่าเอกสารจะไม่พูดถึงมัน (ซุกซน Microsoft!) แต่ปรากฎว่าตัวสร้างดัชนีสำหรับ DataGridView ในความเป็นจริงแล้วจะโยน ArgumentOutOfRangeException เตือนภัย

คำตอบ:


374

คุณสามารถหาวิธีที่จะทำที่นี่ ในระยะสั้นมันคือ:

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

หากคุณต้องการเพียง getter คุณสามารถใช้ไวยากรณ์คำตอบด้านล่างได้เช่นกัน (เริ่มจาก C # 6)


9
ความคิดเห็นเล็กน้อย: ขึ้นอยู่กับสิ่งที่คุณทำคุณอาจพบว่าเหมาะสมกว่าที่จะทำ: รับ {return base [i]; } set {base [i] = value; }
MikeBaz - MSFT

7
นี่ไม่ใช่การใช้งานเกินกำลัง มันเป็นตัวทำดัชนี
Destructor

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
ในแง่ของวิธีการที่จะนำไปใช้มันเป็น "รายการ" แต่ในแง่ C # ก็คือ "นี้"
Marc Gravell

1
ใช่ แต่ฉันถามว่า "สำหรับชีวิตของฉันฉันไม่สามารถหาเอกสารเกี่ยวกับตัวดำเนินการ index / square-bracket" - ฉันหมายถึงเมื่อคุณค้นหาคลาสไลบรารี่ใน MSDN พวกเขาจะบอกคุณเกี่ยวกับโอเปอเรเตอร์ที่ไหน ว่าทำไมฉันทำที่ล่าสุด "กทพ." เกี่ยวกับสิ่งที่มันจะพ่น - เอกสารที่มีการผิดพลาด
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
ขออภัยถ้าฉันอ่านกระทู้ของคุณผิด แต่คุณอ้างถึงเงื่อนไขอะไร
Charles Bretana

+1 สำหรับรายการที่มีประโยชน์ FYI ลิงก์เสียชีวิต (4 ปีต่อมาฉันรู้)
Mixxiphoid

ฉันต้องการเพิ่มว่าคุณสามารถแทนที่ทั้งการกำหนดประเภทโดยนัยและชัดเจนใน C # ตอนนี้
Felype

9

หากคุณกำลังใช้ C # 6 หรือใหม่กว่าคุณสามารถใช้ไวยากรณ์ที่มีการแสดงออกสำหรับผู้สร้างดัชนีเท่านั้น:

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 # polymorphism: เกิดขึ้นเพราะคลาสพื้นฐานไม่ได้ประกาศว่ามีการใช้งานแบบเสมือน หากมีการประกาศเป็นเสมือนรหัสที่กำหนดเองจะถูกเรียกในทุกกรณี
almulo

1
นอกจากนี้รหัสนี้จะให้คำเตือนคอมไพเลอร์เนื่องจากตัวทำดัชนีทั้งคู่ไม่ใช่แบบเสมือน คอมไพเลอร์จะแนะนำให้คุณมีคุณสมบัติกำหนดดัชนีของคุณเองด้วยnewคำหลัก
amoss

4

สำหรับ CLI C ++ (รวบรวมด้วย / clr) ให้ดูลิงก์ MSDNนี้

ในระยะสั้นทรัพย์สินจะได้รับชื่อ "เริ่มต้น":

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

ถ้าคุณหมายถึง array indexer คุณเกินพิกัดเพียงแค่เขียนคุณสมบัติ indexer .. และคุณสามารถ overload, (เขียนมากเท่าที่คุณต้องการ) คุณสมบัติ indexer ตราบใดที่แต่ละพารามิเตอร์มีลายเซ็นของพารามิเตอร์ที่แตกต่างกัน

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
อันดับแรกคุณหมายถึง [] ไม่ใช่สิ่งนี้ () - อย่างไรก็ตามการให้แบบกำหนดเอง (แต่แตกต่างกัน) นี้ [int] ในบางสิ่งที่เป็นรายการ (IList / IList <T> / รายการ <T>) ค่อนข้างอันตราย - และ อาจนำไปสู่ข้อบกพร่องที่ละเอียดอ่อนระหว่างรุ่น "ดัชนี int" และ "int employeeId" ทั้งสองยังคงโทรได้
Marc Gravell

และในความเป็นจริงฉันไม่คิดว่ารหัสที่ฉันป้อนด้านบนจะรวบรวมโดยไม่ต้องเพิ่มคำสั่งใหม่หรือแทนที่อย่างแม่นยำเพราะการมีอยู่ของรายการ <T> การใช้งานของ [int] นี้ คุณพูดถูกเกี่ยวกับความเป็นไปได้ในการทำสิ่งนี้หมายความว่าเป็นตัวอย่างของการทำดัชนีมากเกินไป
Charles Bretana
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.