| 

.NET C# Java Javascript Exception

8
Hallo, eine Frage an die Reflectionexperten unter euch:

Gegeben ist folgende Klassenstruktur:

public class A{
[MyAttribute1]
public string field;
}
public class B : A{
[MyAttribute2]
[MyAttribute3]
public string field;
}


Mittels Reflection versuche ich nun herraus zu bekommen ob das jeweilige Feld das Attribute "MyAttribute2" hat oder nicht.
Dazu gehe ich die einzelene Felder von "B" durch und bekomme folgenden Output:

foreach (FieldInfo field in TypeOfB.GetFields(BindingFlags.Public | BindingFlags.Instance))
{
Console.Write(field.DeclaringType);
Console.Write(" : ");
Console.Write(field.GetCustomAttributes(false).Length);
Console.Write("\n");
}

//Output:
A.field : 1
B.field : 2


Erwarten tuh ich jedoch folgenden Output:

B.field : 3


Nun die Frage. Kann mir einer erklären warum ich "field" 2x bekomme und nicht kombiniert? Und vorallem, kann mir wer sagen wie ich es richtig mache?
News:
16.07.2013
Floyd 14,6k 3 9
1 Antwort
5
Hi Floyd,

die unmittelbare Antwort gibt Dir eigentlich schon der Compiler: B.field sollte grün unterstrichen sein, dazu die Warnung:
"B.field" blendet den vererbten Member "A.field" aus. Verwenden Sie das new-Schlüsselwort, wenn das Ausblenden vorgesehen war.

Du kannst Felder in C# nicht überschreiben. Dein Code erzeugt zwei Felder "field", eins in B und eins in A, von denen das eine das andere verbirgt, die aber technisch gesehen trotzdem zwei Felder sind, von denen jedes seine eigenen Attribute hat. Siehe auch hier bei stackoverflow.

Wie Du es "richtig" machst, hängt von Deinem Use Case ab. Du könntest statt des Feldes eine Eigenschaft verwenden (die virtual- und override-Modifizierer nicht vergessen). Du müßtest dann aber beim Überschreiben das "zu erbende" Attribut (also MyAttribute1) nochmal wiederholen. Oder Du schaust Dir mal TypeDescriptor.AddAttribute an, damit könntest Du eventuell zur Laufzeit die Attribute von B modifizieren. Hab ich aber keine Erfahrungen dazu. Oder Du entscheidest Dich aktiv für das Verbergen, ergänzt auch diesmal MyAttribute1 und beschränkst Dich bei der Abfrage auf die in B deklarierten Felder:

public class B : A{
[MyAttribute1]
[MyAttribute2]
[MyAttribute3]
public new string field;
}

...

foreach (FieldInfo field in TypeOfB.GetFields(BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly))
{
...
}


Achtung: bei der dritten Variante hantierst Du in A-Code immer mit A.field, welches in B-Code nur via Casting sichtbar wird.
16.07.2013
Matthias Hlawatsch 13,2k 4 9
Werd die Variante mit den Properties benuzten. Danke für die ausführliche Antwort.

Anbei, hab die selbe Frage auch noch auf Stackoverflow gestellt und hier noch ein Querverweis für die, die es interessiert: http://stackoverflow.com/questions/17685548/reflection-of-an-overridden-field-returns-the-field-several-times

Deine Antwort ist jedoch um länge ausführlicher :)
Floyd 16.07.2013
PS: Antwort akzeptieren geht auch nicht ... Keine Fehlermeldung, geht einfach nur nicht
Floyd 16.07.2013
Schnief, hatte ich befürchtet ;-) Schreib doch nochmal an Andreas (und vielleicht kann er ja sogar stellvertretend akzeptieren).

So oder so: freut mich, dass ich helfen konnte.
Matthias Hlawatsch 16.07.2013
Hab ich schon gemacht ;) Wünsch dir, das er es auch macht / machen kann
Floyd 16.07.2013
Habe die Bewertung für Dich gemacht!
Claus M. 17.07.2013
Danke Claus
Floyd 17.07.2013
Von mir gibrts für die lange Antwort noch einen Punkt oben drauf. Und ebenfalls ein Danke an Claus :-).
Andreas_mod 17.07.2013
@Andreas: Wäre schön wenn du die Antwort in meinem Namen akzeptieren kannst, da ich es selbst nicht kann
Floyd 17.07.2013
+1 tolle, ausführliche Antwort mit Informationen, die ich selbst auch gebrauchen kann :)
(wenngleich ich eher selten öffentliche Felder nutze, sondern Properties... durch auto-generiertes privates Feld ist das ja kaum mehr Code)
Karill Endusa 17.07.2013
@Floyd: Das Recht zur Markierung korrekter Beiträge habe ich derzeit nicht, aber ich habe das an die Seitenbetreiber weitergeleitet und ich hoffe die korrekte Markierung wird dort schnell gesetzt.
Andreas_mod 17.07.2013
@Andreas: Danke, vielleicht schaut er sich ja auch gleich den Bug mal mit an :)
Floyd 17.07.2013
@Floyd: Auch dies habe ich bereits noch einmal entsprechend weitergegeben ;-).
Andreas_mod 17.07.2013
@Floyd: Habe die Antwort jetzt in Deinem Namen als korrekt markiert.
Andreas_mod 30.07.2013
@Andreas: Danke
Floyd 30.07.2013
@Andreas + Floyd: Auch von mir ein herzliches Dankeschön!

@Andreas: Hat denn inzwischen wenigstens mal jemand herausgefunden, warum Floyd und ich nicht mehr bewerten können? Ist doch eigentlich einfach nachzustellen und 100% reproduzierbar.
Matthias Hlawatsch 31.07.2013
Dieser Fehler ist an die Entwickler gemeldet. Ich selbst kann erst seit gestern Fremdbeiträge als korrekt markieren. Ich hoffe, dass auch der andere Fehler bei den Bewertungen möglichst schnell behoben wird.
Andreas_mod 31.07.2013

Stelle deine .net-Frage jetzt!
TOP TECHNOLOGIES CONSULTING GmbH