Indexer und Item

  • C#

Es gibt 7 Antworten in diesem Thema. Der letzte Beitrag () ist von MasterQ.

    Indexer und Item

    Moin,

    ich stehe gerade auf dem Schlauch.

    Wie deklariere ich in C# einen Indexer und ein Item-Property ?

    neben

    C#-Quellcode

    1. myClass.Item(key)
    soll auch

    C#-Quellcode

    1. myClass[key]
    möglich sein, so wie z.B. bei Collections.


    Wenn ich nun das mache:

    C-Quellcode

    1. public Object Item(string Key , int Index=0) {...; return ans; }
    2. public Object this[string Key] { get { return Item(Key); } }


    heißt es, es gäbe schon eine Definition für Item.

    Gleiches gilt für

    C#-Quellcode

    1. public Object this[string Key] => Item(Key);



    Wie geht's denn richtig, also dass ich sowohl

    C#-Quellcode

    1. myClass.Item()
    als auch

    C#-Quellcode

    1. MyClass[]
    nutzen kann. Bei Collectiosn etc geht das doch auch?

    Nachtrag:

    Schreibe ich nur den Indexer, dann compiliert myClass aber der Rest der Anwendung nicht, denn da gibt es dann doch (Ätschi Bätschi) kein myClass.Item!! ?(

    Gruß

    MQ

    Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von „MasterQ“ ()

    Hey,

    sobald Du eine Property als Default deklarierst, wird im Hintergrund automatisch eine Property mit dem Namen Item erstellt. Aus diesem Grund kannst Du keine weitere Property mit dem Namen Item haben.

    Nachtrag...

    Aus dieser Klasse =>

    C#-Quellcode

    1. public class Test
    2. {
    3. private List<int> _numbers = new List<int>(Enumerable.Range(0, 1000));
    4. public int this[int index]
    5. {
    6. get => _numbers[index];
    7. set => _numbers[index] = value;
    8. }
    9. }


    wird dieser IL-Code....

    Die Unendlichkeit ist weit. Vor allem gegen Ende. ?(
    Manche Menschen sind gar nicht dumm. Sie haben nur Pech beim Denken. 8o

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „SpaceyX“ ()

    Ja, das lese ich aus den Meldungen des Compilers.

    eine Property Item ist aber außerhalb der Klasse nicht vorhanden. Da heißt es auch nicht, dass die Zugriffsebene nicht stimmt oder sonstiges, das darauf schließen lässt, dass Item überhaupt existiert. Item gibbet außerhalb nit! Der Indexer ist public, Item wird (intern) angelegt, lässt sich so aber nicht ansprechen.

    Das sollte aber doch möglich sein, wie alles was auf Collection beruht zeigt.

    Irgendwas ist da doch falsch!

    C#-Quellcode

    1. public class myClass{
    2. private List<int> _numbers = new List<int>(Enumerable.Range(0, 1000));
    3. public int this[int index] {
    4. get => _numbers[index];
    5. set => _numbers[index] = value;
    6. }
    7. }
    8. class Test {
    9. myClass mC = new myClass();
    10. void s(){
    11. int a = mC[1];
    12. int b = mC.Item(1);
    13. }
    14. }
    15. }


    zeigt bei mC.Item rote Kringellinie und dass es für Item keine Definition gäbe


    Dieser Beitrag wurde bereits 3 mal editiert, zuletzt von „MasterQ“ ()

    MasterQ schrieb:

    C#-Quellcode

    1. myClass.Item(1);
    Machst Du

    C#-Quellcode

    1. mc.Item(1);
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    @MasterQ

    Ich verstehe schon, was Du erreichen willst. Ich hab jetzt wirklich die letzte Stunde versucht, das für Dich rauszufinden. Was ich Dir sagen kann, dass es in C# wohl nicht geht, dass Du eine IndexerProperty mit dem Namen Item hast. VB tickt hier anders....

    VB.NET-Quellcode

    1. Public Class Form1
    2. Public Sub New()
    3. InitializeComponent()
    4. Dim test = New Test()
    5. test(10) = 11
    6. test.Item(11) = 100
    7. End Sub
    8. End Class
    9. Public Class Test
    10. Private _numbers As New List(Of Integer)(Enumerable.Range(0, 1000))
    11. Default Public Property Item(index As Integer) As Integer
    12. Get
    13. Return _numbers(index)
    14. End Get
    15. Set(value As Integer)
    16. _numbers(index) = value
    17. End Set
    18. End Property
    19. End Class


    Das ist in VB.Net ohne Probleme möglich. Aus welchem Grund brauchst Du das denn genau? Ich kann mir jetzt keinen rechten Sinn dahinter vorstellen, 2 Möglichkeiten zu haben, die das selbe machen.....
    Die Unendlichkeit ist weit. Vor allem gegen Ende. ?(
    Manche Menschen sind gar nicht dumm. Sie haben nur Pech beim Denken. 8o

    RodFromGermany schrieb:

    MasterQ schrieb:

    C#-Quellcode

    1. myClass.Item(1);
    Machst Du

    C#-Quellcode

    1. mc.Item(1);



    joahh, hatte ich so eingetippert ohne aus VS zu kopieren. Ändert aber nix am Problem.


    SpaceyX schrieb:

    @MasterQ

    Ich verstehe schon, was Du erreichen willst. Ich hab jetzt wirklich die letzte Stunde versucht, das für Dich rauszufinden. Was ich Dir sagen kann, dass es in C# wohl nicht geht, dass Du eine IndexerProperty mit dem Namen Item hast. VB tickt hier anders....

    ...

    Das ist in VB.Net ohne Probleme möglich. Aus welchem Grund brauchst Du das denn genau? Ich kann mir jetzt keinen rechten Sinn dahinter vorstellen, 2 Möglichkeiten zu haben, die das selbe machen.....


    Ich komme von VB, von daher ist mir die Sache nicht fremd.

    Brauchen tu es nicht, hätten hätt ichs aber schon gerne! Ich habe Code, der vielfach Item verwendet, jetzt stieß ich auf den Indexer und wollte damit einfach Tipperei sparen. Entweder muss ich bei item bleiben oder den bisherigen Code ändern. Ist kein Beinbruch aber trotzdem blöd.
    Hi,
    du könntest das Problem mit dem IndexerName Attribut umgehen (siehe docs.microsoft.com/en-us/dotne…rs/using-indexers#remarks )

    C#-Quellcode

    1. public Object Item(string Key, int Index = 0) => ...;
    2. [IndexerName("GetItem")]
    3. public Object this[string Key] { get { return Item(Key); } }


    Ich würde dennoch empfehlen, nicht gegen C# zu kämpfen, sondern den Indexer einzuführen und eben die Item(..) aufrufe ändern, auch wenn das erstmal Arbeit ist.
    Für den Moment könntest du auch ein einfaches Refactoring nutzen: Lösche erst den Indexer, nenne dann deine Item Methode mit VS um, beispielsweise zu GetItem(...), und führe dann den Indexer wieder ein. Das behebt den Konflikt und ist sauberer als per Attribut. Dann kannst du Schritt für Schritt die GetItem(..) Aufrufe durch den Indexer ersetzen.