[C#] indexer of operator[]

Pagina: 1
Acties:

Onderwerpen


Acties:
  • 0 Henk 'm!

  • Punkie
  • Registratie: Oktober 2005
  • Laatst online: 15-08 20:48
Als C++-er probeer ik snel te kijken wat de taal C# aan veranderingen bied. Het viel me op dat men een nieuw concept indexers heeft geïntroduceerd met syntax.
type this [type argument]{get; set;}

Kan hetzelfde niet bereikt worden met het definiëren van operator[] zoals in C++? Met overloading dan voor meerdere argumenten en andere types dan int. Het gemis van de get en set accessors van de indexer wordt opgevangen door de accessors van de member welke de indexer toegang voor bied.
Maar in dat geval zou deze syntax evenveel mogelijkheden bieden:
type this [type argument] member_identifier;

Klopt dat? Wat zie ik over het hoofd?

Acties:
  • 0 Henk 'm!

  • H!GHGuY
  • Registratie: December 2002
  • Niet online

H!GHGuY

Try and take over the world...

Punkie schreef op zaterdag 19 maart 2011 @ 16:24:
Als C++-er probeer ik snel te kijken wat de taal C# aan veranderingen bied. Het viel me op dat men een nieuw concept indexers heeft geïntroduceerd met syntax.
type this [type argument]{get; set;}

Kan hetzelfde niet bereikt worden met het definiëren van operator[] zoals in C++? Met overloading dan voor meerdere argumenten en andere types dan int. Het gemis van de get en set accessors van de indexer wordt opgevangen door de accessors van de member welke de indexer toegang voor bied.
Maar in dat geval zou deze syntax evenveel mogelijkheden bieden:
type this [type argument] member_identifier;

Klopt dat? Wat zie ik over het hoofd?
Je moet die get/set wel nog implementeren...

C#:
1
2
3
4
5
public class MyCollection
{
  private Dictionary<int, SomeClass> _dict;
  public SomeClass this[int index] { get { return _dict[index]; } set { _dict[index] = value; } }
}

Om maar iets te schrijven.

ASSUME makes an ASS out of U and ME


Acties:
  • 0 Henk 'm!

  • Punkie
  • Registratie: Oktober 2005
  • Laatst online: 15-08 20:48
Mijn vraag was niet hoe dit nu geïmplementeerd is maar waarom er een aparte syntax voor gedefinieerd is. Me dunkt dat er al equivalente functionaliteit bestaat en dat er geen uitbreidingen op de taal nodig zijn omdat operator[] kan geherdefinieerd worden.

C#:
1
2
3
4
5
public class MyClass
{
  private List<SomeClass> _list;
  public SomeClass operator[](int index) { return (index%SOME_MAX<_list.count())?_list[index],NULL;} // some calc
}

Acties:
  • 0 Henk 'm!

  • Jaap-Jan
  • Registratie: Februari 2001
  • Laatst online: 17:23
En hoe kun je dan setten?

| Last.fm | "Mr Bent liked counting. You could trust numbers, except perhaps for pi, but he was working on that in his spare time and it was bound to give in sooner or later." -Terry Pratchett


Acties:
  • 0 Henk 'm!

  • Punkie
  • Registratie: Oktober 2005
  • Laatst online: 15-08 20:48
Zoals iedere assignment?
C#:
1
2
Myclass a= new MyClass();
a[2] = new SomeClass();

In C++ zou de operator[] een SomeClass reference returnen welke als lvalue dient voor de assignment.

Acties:
  • 0 Henk 'm!

  • Woy
  • Registratie: April 2000
  • Niet online

Woy

Moderator Devschuur®
Punkie schreef op maandag 21 maart 2011 @ 12:17:
In C++ zou de operator[] een SomeClass reference returnen welke als lvalue dient voor de assignment.
Alleen werkt de assignment operator niet op dezelfde manier in C# als in C++, en daarom is de Indexing methode IMHO een stuk duidelijker.

Sowieso heb je in C++ veel meer vrijheid om operators te overloaden. In C# hebben ze dat beperkt gehouden, en hoewel dat wel wat limitaties met zich meebrengt, voorkomt het ook een hoop mogelijke complexiteit.

[ Voor 23% gewijzigd door Woy op 21-03-2011 12:33 ]

“Build a man a fire, and he'll be warm for a day. Set a man on fire, and he'll be warm for the rest of his life.”


Acties:
  • 0 Henk 'm!

  • Punkie
  • Registratie: Oktober 2005
  • Laatst online: 15-08 20:48
Woy schreef op maandag 21 maart 2011 @ 12:31:
Alleen werkt de assignment operator niet op dezelfde manier in C# als in C++, en daarom is de Indexing methode IMHO een stuk duidelijker.
De gebruikte assignment hierboven werkt wel, is het niet? Enkel "a[2]" kan niet maar dat zou dan equivalent zijn aan de get accessor welke SomeClass zou returnen.
C#:
1
2
3
4
5
6
public class MeClass
{
  private SomeClass val {get;set;}
}

MeClass.val = new SomeClass();

Als dit werkt dan zou de assigment na de index operator (operator[]) ook werken. En dus kan operator[] gebruikt worden om hetzelfde te doen als indexers,indien dit niet expliciet was tegengehouden.

Acties:
  • 0 Henk 'm!

  • Haan
  • Registratie: Februari 2004
  • Laatst online: 20:53

Haan

dotnetter

Punkie schreef op maandag 21 maart 2011 @ 13:08:
[...]

De gebruikte assignment hierboven werkt wel, is het niet? Enkel "a\[2]" kan niet maar dat zou dan equivalent zijn aan de get accessor welke SomeClass zou returnen.
C#:
1
2
3
4
5
6
public class MeClass
{
  private SomeClass val {get;set;}
}

MeClass.val = new SomeClass();

Als dit werkt dan zou de assigment na de index operator (operator[]) ook werken. En dus kan operator[] gebruikt worden om hetzelfde te doen als indexers,indien dit niet expliciet was tegengehouden.
Dat werkt echter niet, want ten eerste kan je geen private property buiten een class aanroepen en ten tweede zou de property static moeten zijn om op die manier aan te roepen.

Kater? Eerst water, de rest komt later


Acties:
  • 0 Henk 'm!

  • Woy
  • Registratie: April 2000
  • Niet online

Woy

Moderator Devschuur®
Punkie schreef op maandag 21 maart 2011 @ 13:08:
[...]

De gebruikte assignment hierboven werkt wel, is het niet? Enkel "a\[2]" kan niet maar dat zou dan equivalent zijn aan de get accessor welke SomeClass zou returnen.
Maar jouw voorstel was dat je een lvalue terug geeft waar je de assigment operator van gebruikt. Aangezien je geen invloed hebt op de assignemt in C# is jouw voorstel dus niet mogelijk, aangezien je de assignment operator niet kunt overloaden, en je dus alleen kunt assignen aan variabelen.

Imho is de indexing methode een stuk duidelijker.

Met het overloaden van de operator[] vraag ik me ook af hoe je omgaat met elementen die niet bestaan. Om die te kunnen assignen moet je iets terug geven. Door de indexer oplossing kun je expliciet onderscheid maken tussen de get en set, en kun je bij het opvragen van een niet bestaand item bijvoorbeeld een Exception gooien, maar het assignen wel toestaan.

Maar wat ik me eigenlijk afvraag is waarom je dit op deze manier zou willen doen. Ik vind de oplossing zoals die in C# gekozen is eigenlijk een stuk duidelijker dan de manier waarop je het in C++ zou doen.

[ Voor 4% gewijzigd door Woy op 21-03-2011 13:36 ]

“Build a man a fire, and he'll be warm for a day. Set a man on fire, and he'll be warm for the rest of his life.”


Acties:
  • 0 Henk 'm!

  • Punkie
  • Registratie: Oktober 2005
  • Laatst online: 15-08 20:48
Haan schreef op maandag 21 maart 2011 @ 13:15:
[...]

Dat werkt echter niet, want ten eerste kan je geen private property buiten een class aanroepen en ten tweede zou de property static moeten zijn om op die manier aan te roepen.
oops, idd. Ik wou eigenlijk een member definieren welke je via een instance kon aanspreken.
C#:
1
2
3
4
5
6
7
public class MeClass
{
  public SomeClass val {get;set;}
}

MeClass m = new MeClass();
m.val = new SomeClass();
Woy schreef op maandag 21 maart 2011 @ 13:34:
Maar jouw voorstel was dat je een lvalue terug geeft waar je de assigment operator van gebruikt. Aangezien je geen invloed hebt op de assignemt in C# is jouw voorstel dus niet mogelijk, aangezien je de assignment operator niet kunt overloaden, en je dus alleen kunt assignen aan variabelen.
Ahhh, vermits a[2] geen variable is kan het niet.
MSDN praat over "storage location" http://msdn.microsoft.com/en-us/library/sbkb459w.aspx ipv variable, zowat hetzelfde als C++. a[2] heeft echter ook een storage location.
In de spec wordt storage location niet gedefinieerd. (http://download.microsoft...guage%20Specification.doc) Maar de definitie van een assignment is wel iets anders in de spec "The left operand of an assignment must be an expression classified as a variable, a property access, an indexer access, or an event access."
Zoals Woy schreef, bedankt!

Maar een array access geeft wel een variable terug: "The result of evaluating an array access is a variable of the element type of the array, namely the array element selected by the value(s) of the expression(s) in the expression-list." (echter operator[] != array access)

Nog iets leuk:
C#:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
struct Point
{
    int x, y;
    public Point(int x, int y) {
        this.x = x;
        this.y = y;
    }
    public int X {
        get { return x; }
        set { x = value; }
    }
    public int Y {
        get { return y; }
        set { y = value; }
    }
}
struct Rectangle
{
    Point a, b;
    public Rectangle(Point a, Point b) {
        this.a = a;
        this.b = b;
    }
    public Point A {
        get { return a; }
        set { a = value; }
    }
    public Point B {
        get { return b; }
        set { b = value; }
    }
}
Point p = new Point();
p.X = 100; //valid
p.Y = 100; //valid
Rectangle r = new Rectangle();
r.A.X = 10; //invalid
r.A.Y = 10;//invalid
r.B.X = 100;//invalid
r.B.Y = 100;//invalid

r is een variable. r.A is dat niet.


[edit]
Woy schreef op maandag 21 maart 2011 @ 13:34:
Maar wat ik me eigenlijk afvraag is waarom je dit op deze manier zou willen doen. Ik vind de oplossing zoals die in C# gekozen is eigenlijk een stuk duidelijker dan de manier waarop je het in C++ zou doen.
Omdat ik verschil van mening op je laatste zin. Maar omdat ik geen C# ervaring heb kan ik me beter onthouden van commentaar.
Ik bekeek het ook alleen vanuit het oogpunt van het ontwerp van de taal. En operator overloading arbitrair beperken en de this [] in het leven roepen om toch maar het equivalent te kunnen bieden is een (elegant) ontwerp complex maken(verprutsen). Maar ook variable assignment steekt een stok in de wielen dus.

[ Voor 12% gewijzigd door Punkie op 21-03-2011 15:00 ]


Acties:
  • 0 Henk 'm!

  • Woy
  • Registratie: April 2000
  • Niet online

Woy

Moderator Devschuur®
Punkie schreef op maandag 21 maart 2011 @ 14:51:
[...]
r is een variable. r.A is dat niet.
Dat is eigenlijk nogal een speciaal geval. Je hebt een property die een value-type als resultaat heeft. Als je daar meteen een aanpassing aan zou doen, zonder een kopie van het value-type te maken, heb je er niks aan. Immers heb je de wijziging op een kopie gedaan, waar je later nooit meer bij kunt komen. Als je r.A opvraagt, word er immers een kopie van de value-type gemaakt.

[ Voor 7% gewijzigd door Woy op 21-03-2011 15:14 ]

“Build a man a fire, and he'll be warm for a day. Set a man on fire, and he'll be warm for the rest of his life.”

Pagina: 1