Autor |
Beitrag |
Palladin007
      
Beiträge: 1282
Erhaltene Danke: 182
Windows 11 x64 Pro
C# (Visual Studio Preview)
|
Verfasst: Sa 22.06.13 16:31
Moin,
ich habe mir ein eigenes Attribut geschrieben, das eigentlich sehr einfach gebaut ist.
Das ist nach diesem Prinzip geschrieben:
C#-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15:
| [AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)] public class CryptingPluginAttribute : Attribute { private string _Variable;
public string Variable { get { return _Variable; } }
public CryptingPluginAttribute(string Wert) { this._Variable = Wert; } } |
Insgesamt hat der Konstruktor einen Parameter vom Typ einer Enumeration, der wiederum einen int-Wert repräsentiert.
Es folgen 5 Strings, die angegeben werden müssen und ein optionaler String.
Und so sehen auch die Eigenschaften aus. Zu jedem Parameter eine private Variable und eine Eigenschaft nur mit einem get-Accessor.
Nun kann ich das Attribut also so verwenden:
C#-Quelltext 1: 2: 3:
| using pm = Projekt.DerNamespace;
[pm.AttributeNameAttribute(pm.EnumTyp.Wert1, "Ein String", "Noch ein String", "str", "123", optionalerParameter = "ein String")] |
Das verwende ich an drei Stellen im Code, auf zwei Projekte aufgeteilt.
Im Fehler wird keine Zeile oder Datei angegeben, nur, in welchem Projekt der Fehler ist.
Zitat: | Ein Attributargument muss ein constant-, typeof- oder Arrayerstellungsausdruck eines Attributparametertyps sein.
|
Dass die Zeilen, wo ich das Attribut verwende, die Fehlerquelle sind, weiß ich, weil immer ein Fehler verschwindet, wenn ich eine dieser Zeilen entferne.
Aber was ist nun das Problem?
Wenn ich eine Methode darin verwenden würde oder sowas, ok, aber die Fehler gibt es sogar, wenn ich so schreibe:
C#-Quelltext 1: 2: 3:
| using pm = Projekt.DerNamespace;
[pm.AttributeNameAttribute(1, "string", "string", "string", "string")] |
Meines Wissens nach sind das alles constant-Typen, oder täusche ich mich da?
Ich kann mir das echt nicht erklären. Den selben Fehler hatte ich vorher auch schon mal im selben Projekt, aber da wurde mir eine Zeile gezeigt und ich hab gesehen, dass ich eben gerade das wirklich falsch gemacht habe. Korrigiert und der Fehler war weg, aber diese drei Fehler krieg ich nicht beseitigt.
Kann mir da vielleicht jemand helfen?
Zuletzt bearbeitet von Palladin007 am Sa 22.06.13 21:04, insgesamt 1-mal bearbeitet
|
|
Ralf Jansen
      
Beiträge: 4708
Erhaltene Danke: 991
VS2010 Pro, VS2012 Pro, VS2013 Pro, VS2015 Pro, Delphi 7 Pro
|
Verfasst: Sa 22.06.13 18:37
Zitat: | Insgesamt hat der Konstruktor einen Parameter vom Typ eines Enumerators, der wiederum einen int-Wert repräsentiert. |
Da ist dir irgendwie Enum mit Enumerator durcheinander geraten richtig?
|
|
Palladin007 
      
Beiträge: 1282
Erhaltene Danke: 182
Windows 11 x64 Pro
C# (Visual Studio Preview)
|
Verfasst: Sa 22.06.13 21:03
Ja, stimmt, ich meine natürlich eine Enumeration.
Der Typ ist auch nicht weiter komplex, enthält nur zwei Möglichkeiten, die so zählen, wie immer gezählt wird, wenn ich es nicht angebe: 0 und 1
Aber 0 und 1 ist so konstant, wie es nicht konstanter sein könnte, was ist denn das Problem?
|
|
Ralf Jansen
      
Beiträge: 4708
Erhaltene Danke: 991
VS2010 Pro, VS2012 Pro, VS2013 Pro, VS2015 Pro, Delphi 7 Pro
|
Verfasst: Sa 22.06.13 21:25
Zeig uns mal das konkrete Problem so im allgemeinen funktioniert das. Wenn es bei dir nicht geht brauchen wir das schon den konkreten Code.
|
|
Palladin007 
      
Beiträge: 1282
Erhaltene Danke: 182
Windows 11 x64 Pro
C# (Visual Studio Preview)
|
Verfasst: Sa 22.06.13 21:32
Das Attribut:
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: 41: 42: 43: 44: 45:
| [AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)] public class CryptingPluginAttribute : Attribute { private string _EncryptionName; private string _EncryptionTechnology; private string _Author; private string _AuthorContact; private string _Version; private CryptingTypes _CryptingType;
public CryptingTypes CryptingType { get { return _CryptingType; } } public string EncryptionName { get { return _EncryptionName; } } public string EncryptionTechnology { get { return _EncryptionTechnology; } } public string Author { get { return _Author; } } public string AuthorContact { get { return _AuthorContact; } } public string Version { get { return _Version; } }
public CryptingPluginAttribute(CryptingTypes CryptingType, string EncryptionName, string EncryptionTechnology, string Author, string Version, string AuthorContact = null) { this._CryptingType = CryptingType; this._EncryptionName = EncryptionName; this._EncryptionTechnology = EncryptionTechnology; this._Author = Author; this._AuthorContact = AuthorContact; this._Version = Version; } } |
Die Enumeration:
C#-Quelltext 1: 2: 3: 4: 5:
| public enum CryptingTypes { Synchron, Asynchron } |
Und so verwendet:
C#-Quelltext 1:
| [pm.CryptingPluginAttribute(pm.CryptingTypes.Asynchron, "EncryptionName", "EncryptionTechnology", "ein Name", "1.0.0.0", AuthorContact = "email@yahoo.de")] |
Mehr gibts nicht, das ist alles was ich bieten kann.
|
|
Ralf Jansen
      
Beiträge: 4708
Erhaltene Danke: 991
VS2010 Pro, VS2012 Pro, VS2013 Pro, VS2015 Pro, Delphi 7 Pro
|
Verfasst: Sa 22.06.13 23:34
AuthorContact hat nur einen Getter. Wenn du den benamsten Parameter AuthorContact meinst dann solltest du einen Doppelpunkt verwenden und kein Gleichheitszeichen.
Ansonsten sehe ich an deinem Code kein Problem. Sollte funktionieren.
|
|
Palladin007 
      
Beiträge: 1282
Erhaltene Danke: 182
Windows 11 x64 Pro
C# (Visual Studio Preview)
|
Verfasst: Sa 22.06.13 23:44
Ich hatte ursprünglich auch einen Setter, hab ich dann noch geändert, weil ich beim Einfügen zum Schluss gekommen bin, dass es unpraktisch ist, wenn man die Daten in einem Attribut nachträglich ändern kann.
Ursprünglich war ein Setter und so hab ich das auch verwendet, aber dennoch gab es den Fehler.
...
Hab das gerade noch korrigiert, also Gleichzeichen in Doppelpunkt ändern und da ist mir was aufgefallen:
Nach den Änderungen in zwei Dateien, wo ich diesen optionalen Parameter verwende, gab es nur noch einen Fehler. Der wurde in dem Projekt angezeigt, wo die dritte Datei liegt, wo ich das Attribut verwende, allerdings nutze ich dort nicht den optionalen Parameter.
Da kam mir die Idee, vielleicht stört den das null des optionalen Parameters?
Hab also mal den optionalen Parameter in einen leeren String geändert und jetzt gibt es auch keinen Fehler mehr.
Das ist also der Fehler, was mich aber wundert, ist null für einen string nicht auch ein konstanter Typ?
|
|
Th69
      

Beiträge: 4798
Erhaltene Danke: 1059
Win10
C#, C++ (VS 2017/19/22)
|
Verfasst: So 23.06.13 14:24
Hallo Palladin007,
optionale Parameter haben so ihre Tücken, s. Optionale Parameter (Abschnitt "Kritik an optionalen Parametern") und Optionale Parameter in C#: Gut oder schlecht.
Sie sollten also möglichst nur innerhalb einer Assembly verwendet werden oder aber der Standardwert von Anfang an unverändert bleiben (damit man nicht alle anderen Assemblies neu kompilieren muß).
|
|
Palladin007 
      
Beiträge: 1282
Erhaltene Danke: 182
Windows 11 x64 Pro
C# (Visual Studio Preview)
|
Verfasst: So 23.06.13 18:09
Ja, optionale Parameter verwende ich nur innerhalb der selben Anwendung, oder, wenn ich einen Parameter mit im Konstruktor haben möchte, der aber nicht zwingend nötigt ist und genauso gut null sein kann - wie z.B. bei diesem Attribut.
Deine Links werde ich mir mal anschauen, vielleicht finde ich da auch eine Erklärung, warum null nicht geht, nur ein leerer String.
|
|
Th69
      

Beiträge: 4798
Erhaltene Danke: 1059
Win10
C#, C++ (VS 2017/19/22)
|
Verfasst: Mo 24.06.13 10:33
Aber du hast doch geschrieben
Palladin007 hat folgendes geschrieben: | Das verwende ich an drei Stellen im Code, auf zwei Projekte aufgeteilt.
Im Fehler wird keine Zeile oder Datei angegeben, nur, in welchem Projekt der Fehler ist. |
?!
|
|
Palladin007 
      
Beiträge: 1282
Erhaltene Danke: 182
Windows 11 x64 Pro
C# (Visual Studio Preview)
|
Verfasst: Di 25.06.13 02:50
Ich verwende optionale Parameter verwende ich nur innerhalb der selben Anwendung, oder, wenn ich einen Parameter mit im Konstruktor haben möchte, der aber nicht zwingend nötigt ist und genauso gut null sein kann - wie z.B. bei diesem Attribut.
Hier kann der Parameter auch einfach weg gelassen werden und das wird sich auch nicht weiter ändern, weil der Parameter schlicht nicht wichtig ist.
Nagut, ich könnte eigentlich auch dafür den Konstruktor überschreiben, aber - trotz der Kritik - finde ich es bei sowas besser, einen optionalen Parameter zu verwenden, da hier ja dieser optionale Parameter sichtbar ist, nicht aber bei der Überschreibung.
Den Punkt hab ich auch nicht ganz verstanden. Wenn ich mich nicht irre, wurde doch auch der Kritikpunkt genannt, dass man nicht sehen kann, ob dieser Parameter sich ändern könnte, aber man sieht den ja eigentlich doch: (Bild im Anhang)
Außerdem sieht man den bei der Methode-Überschreibung überhaupt nicht und geändert werden kann dieser Parameter, der bei der Konstruktor-Version, wo er fehlt, eigentlich auch, ohne dass das Änderungen an dem Code, wo es verwendet wird, nötig werden.
Einloggen, um Attachments anzusehen!
|
|
Th69
      

Beiträge: 4798
Erhaltene Danke: 1059
Win10
C#, C++ (VS 2017/19/22)
|
Verfasst: Di 25.06.13 11:02
Hallo Palladin007,
das Problem mit optionalen Parametern ist (wie in deinem Fall das Ändern von "" auf null oder umgekehrt), daß sich nicht automatisch alle Aufrufe aus anderen Projekten dabei mitändern (sondern nur, wenn diese Assemblies auch neukompiliert werden).
Bei überschriebenen Methoden ist dies dagegen nicht der Fall, da ja die Änderung innerhalb der einen Assembly stattfindet (und somit bei Aufruf aus anderen Assemblies automatisch der neue Parameter verwendet wird).
|
|
Palladin007 
      
Beiträge: 1282
Erhaltene Danke: 182
Windows 11 x64 Pro
C# (Visual Studio Preview)
|
Verfasst: Mi 26.06.13 11:25
Aber wenn die Assembly, die den optionalen Parameter irgendwo bereit stellt, einen anderen Standard-Wert erhält und darauf neu kompiliert wird, dann verwenden alle anderen Assemblys diesen neuen Standard-Wert auch - voraus gesetzt, sie nutzen die neue Version.
Wenn aber irgendwo dieser Standard-Wert gar nicht genutzt wird, sondern der optionale Parameter auch als solcher verwendet wird, dass ein Parameter übergeben wird, dann ist doch auch die Änderung im Standard-Wert egal, da er ja deshalb immer noch nicht verwendet wird.
Irgendwie verstehe ich nicht das Problem, ich sehe die optionalen Parameter immer noch als kompakte Schreibweise für Überschreibung von Methoden.
Und gerade, wenn eine ganze Reihe von Eigenschaften existiert, die aber nach der Instanziierung nicht mehr direkt änderbar sein sollen, dann ist es doch ganz praktisch, wenn man die Parameter im Konstruktor stellt, die zwingend eine User-Eingabe erfordern und die anderen Eigenschaften dahinter, aber optional. Dann kann der Nutzer sich selber raus suchen, was er in welcher Reihenfolge verwendet, ohne, dass dafür bei irgendeiner Eigenschaft der set-Accessor nach außen hin sichtbar sein muss.
Und genau dann verwende ich das eigentlich auch, wenn ich bei der Instanziierung einige Eigenschaften zur Definierung bereit stellen möchte, die aber danach, am Objekt selber, nicht mehr änderbar sein dürfen. Wenn sie geändert werden dürfen, lasse ich das dann aber auch weg, da man ja die Eigenschaft direkt nutzen kann.
|
|
Ralf Jansen
      
Beiträge: 4708
Erhaltene Danke: 991
VS2010 Pro, VS2012 Pro, VS2013 Pro, VS2015 Pro, Delphi 7 Pro
|
Verfasst: Mi 26.06.13 12:11
Zitat: | Irgendwie verstehe ich nicht das Problem, ich sehe die optionalen Parameter immer noch als kompakte Schreibweise für Überschreibung von Methoden. |
Problem ist das eben unerwartetes passieren kann deren Auswirkung nicht mit Zeitpunkt der Änderung zusammenfällt. Nur durch kompilieren deines Codes ohne Änderung dieses Codes kann sich das Verhalten ändern womit eben nicht zu rechnen ist.
Stell dir vor du hast eine Anwendung und bei irgendeinem Update bekommst du einen Hotfix fürs .Net Framework das einen geänderte Defaultwert für einen optionalen Parameter enthält (Dafür gehörten die dann geschlagen ist aber ein anderes Thema). Deine Anwendung wird weiterhin den alten Wert für den Parameter verwenden auch wenn es nun gegen den neuen Code läuft. Wenns böse läuft geht deine Anwendung auch einfach weiter weil der alte Defaultwert auch weiterhin der Richtige wäre. Aus irgendeinem Grund kompilierst du die Anwendung neu, irgendeine Stelle y muß geändert werden. Nun knallt es aber plötzlich an der unbeteiligten Stelle x und dann beginnt das Ratespiel. Man sucht ja erstmal nach seinen eigenen Fehlern und wie das mit seinen Änderungen zusammenhängt. Das mit irgendeinem Hotfix der Vergangenheit zusammenzubringen ist ja kaum drin. Im schlimmsten Fall merkt man nicht mal das jetzt die Stelle x sich anders verhält weil man da nicht hinschaut. Man war ja woanders beschäftigt.
Wenn man seinen Code komplett selbst im Griff hat ist das kein Problem. Aber man gewöhnt sich halt einen gewissen Programmierstil an der schwer anzupassen ist wenn man sich in einem anderen Context bewegt. Wenn man überhaupt bemerkt das man das in diesem Context dann nicht mehr tun sollte.
|
|
Palladin007 
      
Beiträge: 1282
Erhaltene Danke: 182
Windows 11 x64 Pro
C# (Visual Studio Preview)
|
Verfasst: Do 27.06.13 09:34
Ja, das habe ich verstanden, aber was ist da denn dann der Unterschied zu einer einfachen Überladung der Methode?
Dann wird da der Operator halt nicht aufgeführt, sondern ganz weg gelassen und innerhalb der Methode wird dann der fehlende Wert eingetragen - also im Prinzip auch ein Default-Wert und da einen Fehler zu finden ist erst recht schwer, weil ich dann ja nicht einmal sehe, wie der Default-Wert ist und ob er geändert wurde. Bei den optionalen Parametern sehe ich den wenigstens, wenn ich nach schaue, denn der Parameter ist dennoch auf geführt und der Wert steht auch dahinter.
|
|
Ralf Jansen
      
Beiträge: 4708
Erhaltene Danke: 991
VS2010 Pro, VS2012 Pro, VS2013 Pro, VS2015 Pro, Delphi 7 Pro
|
Verfasst: Do 27.06.13 11:09
Ich/wir reden von dem Fall das man eine andere Assembly verwendest die ein scheinbar nicht geändertes Interface hat (Defaultwerte sind nicht mehr Teil der Signatur zur Laufzeit). Du siehst also nix weil du gar nicht auf deine IDE schaust und auch nix kompilierst sondern nur benutzt. Und wenn du kompilierst wäre es auch großer Zufall wenn du gerade auf diese Stelle schaust und bemerkst das sich der DefaultWert geändert hat und das das Auswirkungen hat. Vermutlich willst du kompilieren wegen was völlig anderem.
Anderes konstruiertes Beispiel. Dein Attribute enthält ja den Begriff Plugin.
Stellen wir uns vor jemand anderes hat ein Plugin für deine Anwendung geschrieben. Du bringst für deine Anwendung ein kleines Update raus mit ein paar Bugfixes und geändertem Defaultwert aber intern nicht geändertem Verhalten. Sieht völlig harmlos aus. Dieser andere Jemand denkt sich toll ein Hotfix und verwendet das bereits kompilierte Plugin gegen deine neue Version. Da sein Aufruf weiterhin ungeändert ist und der übergebene Werte weiterhin richtig ist obwohl sich der DefaultWert geändert hat funktioniert alles weiterhin. Irgendwann steht dann in seinem Plugin ein neues Feature an und er programmiert also an seinem Plugin an völlig anderer Stelle irgendwas rum und kompliert dann auch. Wenn jetzt der neue DefaultWert zum ersten mal zieht wird es irgendeine Wirkung entfalten. Und als guter Entwickler wird derjenige der da kompiliert hat voraussichtlich bei Problemen erstmal seinem eigenen neuen Code in Verdacht haben und nicht irgendwas anderes.
Bei einer überladenen Methode wäre das so nicht passiert weil der geänderte Default sofort gezogen hätte. Es hätte also sofort beim Einspielen des Bugfixes Probleme gegeben und es ist dann einfacher den Schuldigen/Die Ursache zu finden.
|
|
Palladin007 
      
Beiträge: 1282
Erhaltene Danke: 182
Windows 11 x64 Pro
C# (Visual Studio Preview)
|
Verfasst: Do 27.06.13 11:19
Zitat: | Bei einer überladenen Methode wäre das so nicht passiert weil der geänderte Default sofort gezogen hätte. Es hätte also sofort beim Einspielen des Bugfixes Probleme gegeben und es ist dann einfacher den Schuldigen/Die Ursache zu finden. |
Jetzt hats Klick gemacht, das gibt Sinn
Daran hab ich nicht gedacht, dass die Änderung der Default-Wertes im optionalen Parameter ja auch gar nicht zum tragen kommen kann, wenn der Aufrufer einen eigenen Wert eingetragen hat und eventuelle Fehler fallen dadurch erst viel schneller auf.
Ja, ich habs kapiert, danke für die viele Geduld beim Erklären 
|
|
Th69
      

Beiträge: 4798
Erhaltene Danke: 1059
Win10
C#, C++ (VS 2017/19/22)
|
Verfasst: Do 27.06.13 12:26
Puh... 
|
|
|