Laden...

Forenbeiträge von renexxl Ingesamt 51 Beiträge

14.06.2006 - 16:51 Uhr

Ich habe ein ähnliches Problem. Angenommen jemand gibt mir seine Assemblies zu seinem Projekt (Projekt A) in Debug- und Release-Build. Diese Assemblies möchte ich in mein Projekt (Projekt B) einbinden, ohne die Dlls am GAC anzumelden.

Im Visual Studio mache ich einen Rechtsklick auf mein Projekt B, waehle Add Reference aus und kann dann mittels Browse eine Assembly auswaehlen. Nehme ich nun die Debug oder die Release Assembly? Die Auswahl die ich treffe, gilt in meinem Projekt B fuer den Debug und Release-Build! Ich kann nicht sagen, dass die Debug-Assembly von Projekt A in meinem Projekt B im Debug-Build und die Release-Assembly von Projekt A in meinem Projekt B im Release-Build verwendet werden soll.

Zu dArignac:

Naja die dll ausm bin Verzeichnis nehmen, das ist ja das Arbeitsverzeichnis.

Hier stimme ich ueberein.

Ob nun Release oder Debug hängt davon ab ob du das ganze debuggst oder halt releast, je nachdem nimmt er das entsprechende Verzeichnis.

Er nimmt nicht das Verzeichnis, sondern man muss es explizit angeben. Du meinst bestimmt den Fall, wenn man bei Add Reference ein anderes Projekt angibt.

16.02.2006 - 11:26 Uhr

Hi Sven!

Schau dir mal folgenden Link an:
http://www.codeproject.com/csharp/CountingProcessors.asp

  • Rene
16.02.2006 - 10:43 Uhr

Hi Herbivore!

Deine Lösung ist genau das, was ich gesucht habe. Die Idee ist wirklich sehr gut. Respekt!

Ich habe deine Klasse in meiner Applikation eingebaut und bislang keinen Fehler festgestellt. Funktioniert alles wie erwartet.

Vielen Dank!

  • Rene
14.02.2006 - 10:11 Uhr

Deine foreach Schleife wird doch eh zu ner for Schleife optimiert wenn du primitive Datentypen nimmst.

Mein Beispiel benutzt einen primitiven Datentyp, in der Praxis nutze ich zumeist nicht primitive Datentypen. Was würde es mir bringen direkt eine for-Schleife zu benutzen?

was heißt denn gleichzeitig?

Mit "gleichzeitig" meine ich "sequentiell innerhalb !einer! foreach-Schleife".

warum schreibst du dir nicht einfach eine methode die als parameter ein array bekommt und dieses dann ausgibt?

Wäre eine Möglichkeit. Ich bin aber der Meinung, dass mein Vorschlag (mit dem +) den Code noch lesbarer macht.

was soll das werden?

Man könnte sich eine Methode schreiben, welche Arrays als Parameter erhält und ein Array als Konkatenation dieser arrays zurückgibt. Ueber das konkatenierte Array kann man dann in einer foreach-Schleife iterieren.

14.02.2006 - 09:05 Uhr

Hallo!

Bei mir häufen sich die Fälle, in denen ich mit foreach über mehrere arrays gleichzeitig iterieren möchte, um redundanten Code zu vermeiden.
Beispiel:


int[] numbers0 = { 1, 2, 3 };
int[] numbers1 = { 4, 5, 6 };

foreach (int i in numbers0)
{
    System.Console.WriteLine(i);
}

foreach (int i in numbers1)
{
    System.Console.WriteLine(i);
}

Stattdessen möchte ich in einer foreach Schleife beide arrays gleichzeitig abarbeiten.
Dies könnte z.B. folgendermaßen aussehen:


foreach (int i in numbers0 + numbers1)
{
    System.Console.WriteLine(i);
}

Insbesondere bei vielen arrays erzeugt man schnell redundanten Code.

Ich könnte mir natürlich ein temporäres Array erzeugen und numbers0 und numbers1 dort reinkopieren. Dies würde aber unnötigen Overhead erzeugen.

  • Rene
18.08.2005 - 11:32 Uhr

vermutlich arbeitet der Thread ja eine Schleife ab. Bei jedem (oder jedem 1000 o.ä.) Durchlauf der Schleife, kannst du auf ein ManualResetEvent warten. Wenn der auf grün (= Set) steht läuft der Thread einfach weiter, wenn der HauptThread auf rot (=Reset) stellt, hält der Thread an.

Hiezu muss ich jeden Algorithmus entsprechend anpassen, um ein Suspend zu ermöglichen. Die Algorithmen sind bei mir in Plugins realisiert und stammen damit zumeist nicht von mir. Dann müsste ich also von jedem, der einen Algorithmus/Plugin schreibt, erwarten, dass er das ManualResetEvent einbaut. Dies möchte ich dem Pluginschreiber nicht zumuten.

Des Weiteren wird bei diesem Ansatz der Algorithmus nicht sofort angehalten, sondern erst beim Ende der Schleife. Dies ist problematisch, falls der Algorithmus bis zum Ende der Schleife noch Events triggered (siehe weiter unten!).

Würde nicht ein herunterstufen der Thread.Priority auf Lowest sogar auch reichen ?... Idealerweise kombiniert mit einer Ueberwachung der Prozessorlast ? Somit könntest Du auf den Eingriff durch den User verzichten... Sobald die Last wieder eine bestimmte Zeit lang tief ist könntest Du die Priority wieder hochfahren...

Falls man das Suspend nur benötigt, um einem anderen Algorithmus den Prozessor zu geben, wäre dein Ansatz akzeptabel. Ich brauche das Suspend aber auch aus anderen Gründen.

Beispielsweise kann es sein, dass ein Algorithmus während seiner Ausführung Events triggered. Ist der Algorithmus suspendiert, so sollen keine Events mehr getriggered werden.

Dies ist durch Heruntersetzen der Priorität nicht zu realisieren.

Trotzdem schonmal vielen Dank für Eure Beiträge.

  • Rene
17.08.2005 - 11:48 Uhr

Ich habe einen Algorithmus, der längere Zeit läuft (in einem eigenen Thread). Der Benutzer soll die Ausführung des Algorithmus anhalten und zu einem späteren Zeitpunkt fortsetzen können, weil er z.B. die CPU für andere Aufgaben benötigt.

  • Rene
17.08.2005 - 11:42 Uhr

Hier findest du Informationen: http://www.vbip.com/miscellaneous/directory-info/dir-info-01.asp

Der Code ist in VB.NET, müsste aber leicht auf C# übertragbar sein.

  • Rene
17.08.2005 - 11:16 Uhr

Hallo!

Ich möchte, dass ein Thread A einen anderen Thread B suspendiert und später wieder aufweckt. Hierzu gibt es die Methoden Thread.Suspend() sowie Thread.Resume(). Diese sind aber leider seit .NET 2.0 als "obsolete" deklariert.

Ich suche nun nach einer Möglichkeit die gleiche Funktionalität mit anderen Klassen/Methoden nachzubilden.

Eine Möglichkeite wäre, Thread.Sleep(Timeout.Infinite) zu verwenden, die Sleep() Methode kann aber nur innerhalb eines Threads aufgerufen werden.

Hat jemande ne Idee?

  • Rene
14.07.2005 - 14:14 Uhr

Wenn die Anwendung geschlossen wird, wird der GC nicht extra aufgerufen. Stattdessen wird einfach der gesamte Speicher, der zu dem Prozess gehörte, auf einen Rutsch weggeschmissen. Das ist an sich nicht schlimm, denn daurch wird ja der Speicher der Objekte auch freigegeben. Nur kann man sich deswegen nicht darauf verlassen, dass der Destruktor, den eine Klasse ggf. implementiert hat, für jedes Objekt auch tatsächlich aufgerufen wird.

Was meinst Du mit "Anwendung geschlossen wird"?

Beim Killen eines Prozesses ist klar, dass der gesamte Speicher ohne Aufruf der Destrukroren freigegeben wird.

Aber ist dies auch der Fall, wenn ich eine Anwendung mittels des "x" beende?

  • Rene
27.06.2005 - 11:44 Uhr

Hallo!

Ich beschäftige mich momentan mit dem Wrappen von C++-Klassen, um diese dann
in .NET einzusetzen. Als Einstieg habe ich folgendes Dokument gefunden:

http://www.gotdotnet.com/team/cplusplus/articles/mcmigrate.doc

Als Einstieg ist dies nicht schlecht, auf konkretere Fragen wie z.B. dem Wrappen von Klassenhirarchien geht es leider nicht ein.

Kennt jemand vielleicht Literatur, die sich mit diesem Thema beschäftigt?

  • Rene
15.06.2005 - 18:23 Uhr

sogar überlegen (Stichwort Mehrfachvererbung).

Endlich mal jemand, der Mehrfachvererbung auch befürwortet 🙂

  • Rene
15.06.2005 - 18:15 Uhr

Mehr oder weniger stimme ich mit dir überein.

Komisch finde ich es, dass ein MemberwiseClone() mit IClonable angeboten wird, obwohl hier ja auch nur eine flache Kopie stattfindet (mit erzeugen einer neuen Instanz) und das Klonen somit auch Seiteneffekte haben kann. Viele Leute sind sich dieser Problematik auch nicht bewusst.

Dann kann man doch auch jedem Object ein "void Copy(object obj)" mitgeben und ein Interface ICopyable anbieten. Das Standard-Copy würde dann wie beim Clone nur eine flache Kopie mit der Gefahr der Seiteneffekte erstellen. Und über ICopyable könnte man dann eine deep copy explizit implementieren.

Sowas habe ich eigentlich erwartet, scheint es aber ja nicht zu geben. Ich werde mir jetzt also das Copy() (ich brauche sowieso nur flache Kopie) mittels Reflection selbst implementieren, obwohl der Compiler leicht effizienteren Code erstellen würde.

ruft für die einzelnen Felder den Standard-Copy-Konstruktor auf. Mit dem Effekt, dass Zahlen kopiert werden, Objekte aber nur als Referenz kopiert werden.

Wird in dem Standard-Assignment Operator, welcher vom Compiler generiert wird nicht lediglich ein memcpy gemacht? Warum sollte der Copy-Konstruktor aufgerufen werden, da man doch keine neue Instanz benötigt?

  • Rene
15.06.2005 - 17:16 Uhr

Wenn ich aber Inhalte kopiere, dann handelt es sich eben um "neue" Inhalte, die angelegt werden. Eine Verbindung besteht nicht mehr und Aktualisierungen erfolgen auch nicht.

Dies bezeichne ich als Klonen. Unter Kopieren verstehe ich das Kopieren von einem Speicherbereich in einen anderen (z.B. memcopy). Beim Kopieren wird für mich also keine neuer Inhalt (Instanz) angelegt, sondern nur beim Clone().

Entweder ich verwende für ein Feld Referenzen oder Kopien. Beides gleichzeitig geht nicht. Weder in C# noch in irgendeiner anderen Sprache. Die beide Konzepte schliessen sich gegenseitig aus.

Ich möchte doch nur das machen, was ich in C++ auch machen kann:


A* a1 = new A(); // "Referenz" auf Instanz I1
A* a2 = new A(); // "Referenz" auf Instanz I2
a1 = a2; // Umsetzen der Referenzen; a1 und a2 verweisen auf I2
\*a1 = *a2; // kopieren des Inhalts von I2 nach I1

Das Feld (a1 bzw. a2) ist eine Referenz und ich möchte die Instanzen auf die die Referenzen verweisen gegenseitig "kopieren".

Aber um es nochmal kurz zu machen: Es gibt keine solche Inhalts-Zuweisung. Ist auch nicht möglich, da die Art der Kopieraktion (Referenz oder Clone) von den Eigenschaften der Klasse abhängig ist (z.B. immutable = Referenzkopie), und diese Eigenschaften sind an der Deklarationen der Member-Klassen nicht ablesbar (es sei denn durch Attribute!!!).

Aber über Attribute wäre es doch problemlos machbar. Der Compiler könnte sogar zur Laufzeit überprüfen, ob man kopieren darf oder nicht. Dies ist vergleichbar mit const in c++. Wäre in dem obigen Beispiel a1 const, so könnte ich die Kopierzuweisung (über Dereferenzierung) nicht machen. Der Unterschied ist, dass const Instanzbezogen und das Attribut (immutable) Klassenbezogen wäre.

Ich verstehe dich jetzt so, dass das Kopieren in C# nicht möglich ist. Mit Kopieren meine ich genau das, was du mit Copy angedeutet hast (a1.Copy(a2)).

Trotzdem denke ich, dass es in der Sprache leicht zu realisieren wäre und verstehe deshalb nicht ganz, warum es nicht existiert.

  • Rene
15.06.2005 - 16:39 Uhr

Man c# und Java vergleichen, aber nie c# und c++, dafür sind die zu wiet auseinander.

C# ist in vielen Punkten aber sehr stark an c++ angelehnt, siehe beispielsweise Operatoren überladen oder Zeiger in C#.

Ich würde C# als eine Mischung von Java und C++ sehen und insofern ist C# mit C++ vergleichbar.

Wir sind mittlerweile aber sehr Offtopic.

  • Rene
15.06.2005 - 16:33 Uhr

Ich verstehe nicht so ganz was du meinst.

Also, gegeben sind zwei Verweise a1 und a2 auf die Instanzen I1 und I2:


A a1 = new A(); // erzeugt Instanz I1
A a2 = new A(); // erzeugt Instanz I2

Der Inhalt von I2 soll nach I1 kopiert werden.

Schreibe ich


a1 = a2.Clone(); // Clone ist überschrieben und liefert Referenz auf I2.

So zeigt a1 danach auf I2. Mit a1 greife ich zwar auf Werte zu, die ich haben möchte,
die Instanz I1 wurde aber keinster Weise verändert.

Sagen wir, wir hätten vor dem Clone eine dritte Referenz a3 gehabt, die die Instanz
I1 referenziert


A a3 = a1; // a3 referenziert I1

Nun würde a3 nach dem Aufruf des Clone und der Zuweisung an a1 nichts davon bemerken, dass eine Aenderung stattgefunden hat. Denn a3 referenziert I1 und an I1 hat sich durch das Clone nichts geändert.

Insbesondere muss man beachten, dass es Fälle gibt, wo Referenzen zugewiesen werden und andere Fälle, wo kopiert werden soll. Man sollte also beide Möglichkeiten haben. Durch Ueberschreiben von Clone bzw. dem =-Operator schliesst man eine Möglichkeit aus (die Referenzzuweisung).

Des Weiteren verändert man den Sinn von Clone bzw. = und den Nachteil haben wir ja schon bei == gesehen!

  • Rene
15.06.2005 - 16:06 Uhr

Erstmal vielen Dank für die Antworten, so richtig hilft es mir aber nicht weiter.

Zu boco25:

das, was du machen willst wiederspricht cih den Grundlagen der OOP

Das, was ich machen will, wird in C++ tagtäglich problemlos eingesetzt.
Hast du Beispiel für deine Behauptung?

und ich she keine Notwendigkeit sowas zu tun.

Mir fallen auf die Schnelle drei Gründe ein:

  1. Performance. Warum soll ich mir mit Clone ein neues Objekt anlegen und somit unnötig Speicher anfordern, wenn das Objekt schon vorliegt?

  2. Andere Klassen, welche eine Referenz auf I1 haben sollten mitbekommen, wenn sich an I1 etwas ändert. Lege ich mir mit Clone ein neues Objekt von I2 an und und weises dieses a1 zu, so wird nichts an I1 geändert und somit kann sonst niemand etwas von der Aenderung mitbekommen.

  3. this ist readonly. Angenommen ich erhalte in einer Memberfunktion von I1 die
    Instanz I2 und möchte den Inhalt von I2 der Instanz von I1 zuweisen. Da ich mich in I1 befinde und this readonly ist, kann ich keine Referenzzuweisung machen. Also muss ich wohl kopieren.

Bei der Zuweisung einer Variable der Referenztypen wird nur der Verweis kopiert.

Ist klar.

Beim Vergleich wird nur Verweis verglichen.

Kommt auf den Vergleich an. Equals vergleicht den Inhalt, ReferenceEquals vergleicht die Verweise.

Zu svenson:

Das Problem ist, dass ich I1 und I2 schon gegeben habe und dann die Zuweisung machen möchte. Würde ich später die Clone Methode benutzen, so hätte ich die Probleme, die ich oben unter 1. und 2. beschrieben habe.

  • Rene
15.06.2005 - 15:20 Uhr

Hallo!

Ich möchte den Inhalt einer Instanz I1 der Klasse A einer anderen Instanz I2 der
Klasse A zuweisen:


A a1 = new A(); // erzeugt Instanz I1
A a2 = new A(); // erzeugt Instanz I2
a1 = a2;

Der Zuweisungoperator weist nur die Referenz zu, kopiert aber nicht den Inhalt
von Instanz I2 nach Instanz I1. Nach der Zuweisung verweisen a1 und a2 auf
die Instanz I2.

Ich möchte aber den Inhalt von I2 nach I1 kopieren. Meine Idee ist, alle Felder der
Klasse A von I2 per Reflection abzufragen und dann I1 zuzuweisen.

Aber ist gibt doch sicherlich eine einfachere Lösung, oder?

  • Rene
15.06.2005 - 09:52 Uhr

Hallo Hendrik!

Ich würde in Managed-C++ (MC++) einen Wrapper für deine C++-Klasse schreiben.
Diesen Wrapper kannst du dann in C# wie eine gewöhnliche .NET-Klasse benutzen.

Insbesondere kommst du dann per Reflection an die Daten der C++-Klasse und
kannst diese dann per XmlTextWriter exportieren.

Einen guten Einstieg zum Implementieren des Wrappers findest du hier:
http://www.gotdotnet.com/team/cplusplus/articles/mcmigrate.doc

  • Rene
13.05.2005 - 08:49 Uhr

Hi herbivore!

Ich möchte mir keinen DeviceContext erstellen, sondern den DeviceContext des Controls abfragen, um in das Control zu zeichnen (z.B. mittles OpenGL).
Insofern scheinen die Win32-API-Funktionen nicht weiterzuhelfen.

Der Weg über Graphics scheint aber eine Möglichkeit zu sein.
Mittels CreateGraphics() kann ich mir für das Control ein Graphics-Objekt erzeugen.
Und über das Graphics-Objekt komme ich per GetHdc() an den DeviceContext.

Ich werde mal probieren, ob dies nun auch in der Praxis funktioniert.

Besten Dank!

-Rene

12.05.2005 - 13:30 Uhr

Hallo!

Ich möchte mittels eines DeviceContexts in ein UserControl zeichnen.
Gibts eine Möglichkeit sich den DeviceContext eines UserControls zu holen?

  • Rene
21.04.2005 - 14:49 Uhr

Hallo!

Ich möchte ein JavaApplet in einer WinForm wie ein Control verwenden.

Am besten wäre es, wenn es ein Control geben würde, welchem man einfach ein
Java Applet übergibt. Ich habe sowas leider nicht gefunden.

Eine andere Idee ist, das ActiveX-Control "Microsoft Webbrowser" zu verwenden.
Diesem kann man die URL übergeben, welche das Applet anzeigt.

Hier habe ich das Problem, dass mir das Control das Applet nicht anzeigt, ich sehe
lediglich einen grauen Kasten. Im IE läuft das Applet problemlos.
Des Weiteren habe ich um das Applet noch einen weissen Rahmen, den
ich nicht wegbekomme.

Für Ideen wäre ich Euch dankbar!

  • Rene
15.04.2005 - 13:37 Uhr

Aber dann sollte das Replace doch funktionieren.

  • Rene
15.04.2005 - 13:34 Uhr

Hallo kl1mm,

habs gerade mal getestet und bei mir funktionierts:


string Betrag = "9,7 €";
Betrag = Betrag.Replace("€","");

In Betrag steht nach dem Replace "9,7 ".

Kannst du deinen Code mal posten?

  • Rene
14.04.2005 - 17:55 Uhr

Hallo Pulpapex!

Scheint zu stimmen. Ich habe folgenden Artikel gefunden: http://www.codeproject.com/dotnet/ilassembly.asp

Dort heißt es:

One another thing you should note that we used instance keyword while calling the method which we have never used. Instance keyword tells the compiler that we are going to call the method of any object’s instance; it is not the static method.

Ich verstehe dies nun so, dass instance quasi das Gegenteil zu static ist. Ein Property kann ohne Instanz aufgerufen werden (static) oder man ruft es auf einer Instanz auf (instance).

Kompiliere ich folgenden Code


public class A 
{
  public static string Name
  {
    get { return "My name is A!"; }
  }
}

so erhalte ich diesen IL-Code:


.property string Name()
{
  .get string Reproducer.A::get_Name()
} // end of property A::Name

Lasse ich in C# das static weg, so erhält man das Wort instance im IL-Code (.property instance und .get instance).

Ist dann aber nicht eins der beiden keywords static und instance redundant?

Mein Ziel ist es, dass ich mit Hilfe eines PropertyBuilders aus dem Emit-Namespace dynamisch ein Property erzeuge, welches nicht static ist, also das keyword instance im IL-Code besitzt.

Die möglichen PropertyAttributes, welche man der Methode DefineProperty mitgeben kann, bieten leider kein static oder instance. Standardmäßig wird static erzeugt.

Beim Erzeugen einer Methode (DefineMethod) kann man mittels MethodAttributes die Methode als static deklarieren, hier wäre der Standard nicht static.

Fehlt nun einfach die Möglichkeit ein nicht-statisches Property per Emit zu erzeugen oder habe ich alles falsch verstanden?

  • Rene
14.04.2005 - 16:52 Uhr

Hi!

Ich möchte wissen, was instance in der Intermediate Language bedeutet, kann aber leider nichts dazu finden.

Insbesondere gehts um das instance bei einer Property-Deklaration: (instance nach .property)


.property instance string Name()
{
  .get instance string Reproducer.B::get_Name()
} // end of property B::Name

Erzeuge ich ein Property mit C#, so erhalte ich den angegebenen IL-Code mit instance.
Erzeuge ich das Property mit PropertyBuilder aus Emit, so ist das instance im IL-Code nicht mehr vorhanden.

Das fehlende instance erzeugt in meinem Code viele Fehler, deshalb möchte ich wissen, wie ich den PropertyBuilder veranlassen kann, das instance zu exportieren.
Dazu würde mir die Bedeutung von instance bestimmt schon weiterhelfen.

Schonmal vielen Dank!

  • Rene
14.04.2005 - 09:34 Uhr

Danke! Genau sowas habe ich gesucht.

  • Rene
13.04.2005 - 17:27 Uhr

Versuchs mal hiermit:


string[] strings = (string[])myList[0];
foreach( string str in strings )
{
        
}

  • Rene
13.04.2005 - 17:14 Uhr

Ich denke auch, dass das Framework ausreichen sollte.

Man kann sich ja seinen eigenen Compiler aus den CodeDom-Klassen bauen.
Der C#-Compiler nutzt bestimmt auch diese Klassen und bietet Zugriff darauf über die Kommandozeile.

  • Rene
13.04.2005 - 14:58 Uhr

Hallo!

Ich benutze PropertyGrids und ärgere mich immer darüber, dass ich die Desciption zu einem Property nicht sehen kann, weil sie zu lang ist.

In einer eigenen Applikation könnte man sich ein eigenes PropertyGrid schreiben, welches z.B. die komplette Description in einem Tooltip anzeigt.

Dieses Problem ist aber auch in Fremdapplikationen gegeben wie z.B. VS2003. Da ich hier keine Möglichkeit habe das PropertyGrid zu verändern, hoffe ich, dass einen Trick gibt, um sich die Description dennoch anzeigen zu lassen.

  • Rene
13.04.2005 - 13:50 Uhr

Hallo Basster,

ich verstehe dich so, dass du C# Quellcode zur Laufzeit eines Programms hast, diesen kompilieren und dann ausführen möchtest.

Hierfür kannst du den Namespace System.CodeDom verwenden. Dieser bietet dir Klassen, um Quellcode zur Laufzeit zu kompilieren.

Du kannst so z.B. eine Klasse, welche in C# Quellcode vorliegt zur Laufzeit kompilieren und dann beliebig Instanzen der Klasse erzeugen.

  • Rene
08.04.2005 - 13:17 Uhr

Mit der Factory habe ich auch so verstanden. Ich werds mal ausprobieren. Vielen Dank für deine Ausführung!

Zitat:
Sie beziehen sich auf das Element, auf das sie angewendet werden.

Was meinst du mit Element? Klasse oder Instanz?

Auf alles, was du in der AttributeTargets Enumeration findest: Assemblies, Klassen, Konstruktoren, Delegaten, Enumerationen, Events, Felder, Typparameter, Interfaces, Methoden, Module, Parameter, Eigenschaften, Rückgabewerte und Strukturen.

Sind die Elemente der Klasse oder der Instanzen gemeint? Wird also pro Klasse oder für jede Instanz der Klasse ein Attribut erzeugt? Ich habs so verstanden, dass ein Attribut pro Klasse erzeugt wird.

  • Rene
08.04.2005 - 12:05 Uhr

@herbivore:

Falls ich die statische Variable über ein Interface erzwungen hätte, dann hätte ich Zugriff über das Interface.
Ansonsten müsste man über Reflection auf die Variable zugreifen.

@VizOne:

Alternativ könntest du ein interface für plug-in Fabriken machen:

Verstehe ich es richtig, dass dann zu jeder Klasse A, die IPlugIn implementiert, eine Klasse B exisitert, die IPlugInFactory implementiert? Von der Klasse A kann es mehrere Instanzen geben, wobei die Klasse B ein Singleton ist?

Sie beziehen sich auf das Element, auf das sie angewendet werden.

Was meinst du mit Element? Klasse oder Instanz?

Jein. Wenn du dir mit GetCustomAttribute eine Attribut-Instanz eines Objektes holst, kannst du dessen Zustand ändern. Aber die Metadaten werden dadurch nicht geändert. Das heißt, dass du beim nächsten GetCustomAttribute eine neue Instanz der Attributklasse erhälst mit den Werten, die bei der Deklaration des Attributs angegeben wurden.

Erreiche ich das Gleiche nicht durch einen statischen, konstanten Member?

Wenn ich den Wert abfrage und in einer Variable speicher, so kann ich den Wert in der Variable verändern. Aber der Wert des statischen, konstanten Members wird nicht geändert. Frage ich den Wert des Members nochmal ab, so erhalte ich den Wert, der bei der Deklaration/Definition des Members angegeben wurde.

08.04.2005 - 11:11 Uhr

Hallo VizOne,

wenn ich nun ein bestimmtes Plugin anhand der GUID suche, müsste ich ja jede Menge Instanzen von Plugins erzeugen.

Ich werde mal schaun, wie es mit Kostanten in Interfaces aussieht.

-Rene

08.04.2005 - 11:06 Uhr

@bitstream:

Vielen Dank! Habe ich mir schon fast gedacht. Zur Not besteht ja die Möglichkeit die Konvention zur Laufzeit zu verifizieren.

Ich sehe zwischen Klassenattribut und statischen Member nur einen syntaktischen aber keinen semantischen Unterschied. Anstatt Klasse.Attribut kann ich halt über GetCustomAttributes auf das Attribut zugreifen. Hierzu noch zwei Fragen:

Ist ein Attribut Instanz- oder Klassenbezogen?
Kann man ein Attribut zur Laufzeit ändern?

Dies könnten semantische Unterschiede zu einem statischen Member sein.

@herbivore:

Die Eigenschaft ist eine GUID eines Plugins. Jedes Plugin soll einen eindeutigen Identifizierer besitzen, wobei die GUID für jede Instanz einer Klasse gleich ist und sich nicht zur Laufzeit ändern darf. Deshalb sind meine Fragen zum Attribut interessant.

Bei einem statischen Member (wenn er denn in einem Interface möglich wäre) besteht ja noch das Problem, dass er sich zur Laufzeit ändern könnte.

In Java sind doch Konstanten in Interfaces möglich, oder? Ist dies auch in C# erlaubt?

  • Rene
08.04.2005 - 10:07 Uhr

Hallo!

Ich möchte von einer Klasse erzwingen, dass sie eine bestimmte statische Eigenschaft enthält. Die Kontrolle, ob eine Klasse die Eigenschaft enthält soll zur Compilezeit erfolgen. Bislang sehe ich folgende Möglichkeiten, wobei keine zufriedenstellend ist:

  1. Statische Eigenschaft in einem Interface zu deklarieren ist nicht möglich.

  2. Deklariere in einem Interface eine nicht statische Eigenschaft. Diese wird in der implementierenden Klasse durch das Interface erzwungen.
    Nachteile: Um auf die Eigenschaft zuzugreifen muss eine Instanz der Klasse erzeugt werden. Jede Instanz enthält die Eigenschaft, wodurch zusätzlicher Speicher verbraucht wird.

  3. Gebe der Klasse ein Attribut, welches die Eigenschaft enthält. Zur Laufzeit kann das Attribut und somit die Eigenschaft per Reflexion abgefragt werden. Der Zugriff auf das Attribut erfolgt ohne Klasseninstanz, die Eigenschaft ist somit static. Leider ist ein Attribut optional, es kann also nicht zur Compilezeit erzwungen werden. Zur Laufzeit besteht die Möglichkeit zu überprüfen, ob das Attribut vorhanden ist.

  4. Anstatt des Attributs könnte doch auch eine statische Eigenschaft in der Klasse verwendet werden. Diese kann wie ein Attribut zur Laufzeit abgefragt werden. Worin besteht eigentlich der Unterschied zwischen einem Klassenattribut und einem statischen Member?

Bislang nutze ich die 2. Möglichkeit, da sie als einzige das Problem löst. Aufgrund der Nachteile bin ich mit der Lösung nicht zufrieden.

Hat sonst jemand eine Idee, was man machen könnte?

  • Rene
01.04.2005 - 14:21 Uhr

Hallo!

Ich möchte zur Laufzeit auf die XML-Dokumentation zugreifen. Dazu müsste die XML-Dokumentation wie Attribute als Metadaten der Klasse abgelegt werden. Dann hätte man über Reflection Zugriff auf die Dokumentation.
Technisch sollte dies kein Problem darstellen, da der Compiler die Dokumentation nur als Metadaten ablegen muss. Gibts sowas vielleicht sogar und kann man dies durch ein Compilerflag erreichen?

Ich brauche dies, um mir Schreibarbeit zu sparen und die Pflegbarkeit des Codes zu erhöhen. Dazu folgendes Beispiel:

Ich habe eine Klasse A, in der ein Property "Name" existiert:


    /// <summary>
    /// Gets or sets the name of the class. 
    /// </summary>
    [Description("Gets or sets the name of the class.")]
    public string Name
    {
      get { return name; }
      set { name = value; }
    }

Zu dem Property gibt es eine XML-Dokumentation. Da ich die Klasse A in einem PropertyGrid einsetzen möchte mit Beschreibung, existiert zusätzlich ein Description-Attribut, welches mit der XML-Dokumentation übereinstimmt.

Man erkennt klar die Redundanz. Dadurch wird der Code unübersichtlicher, ich habe mehr Schreibarbeit (nicht so schlimm, es gibt ja copy&paste 🙂), die Pflegbarkeit des Codes leidet und man kann leicht vergessen die beiden Stellen konsistent zu halten.

Wäre die XML-Dokumentation als Metadaten abgelegt, so könnte ich zur Laufzeit das Attribut erzeugen (Geht doch mit Reflection, oder?).

Ein weiteres Beispiel, wo die Metadaten gebraucht werden können:
Zu einem Plugin wird eine Beschreibung innerhalb der Klasse als static string hinterlegt. Die gleiche Beschreibung steht in der Dokumentation zur Klasse. Hier ist wiederum die Redundanz gegeben.

Also, kennt jemand eine Möglichkeit auf die XML-Dokumentation mittels Metadaten und Reflection zuzugreifen?

  • Rene
18.02.2005 - 17:18 Uhr

Ich uebergebe einen int und B.Foo(object)(!) wird aufgerufen. Ich habs gerade extra nochmal ausprobiert:


public void DoSomething()
{
  object v = 7;
  int w = 7;
  Foo(v);   // Ruft B.Foo(object) auf.
  Foo(w);   // Ruft B.Foo(object) auf.
}

Habe zuerst auch gedacht wie du, habe mich aber von c# eines besseren belehren lassen. Aber dies ist wie schon gesagt nicht die eigentlich Problematik.

  • Rene
18.02.2005 - 16:58 Uhr

Die Methode Foo() in B muss eigentlich so aussehen:


    public void Foo( object obj ) 
    {
      int integer = ObjectToInt( obj );
      base.Foo( integer );
    }

Aendert aber nicht viel, da ja 3 ein int und kein object ist. Es ist wirklich so, dass wenn ich einen int uebergebe B.Foo() und nicht A.Foo() aufgerufen wird.

Um das Problem etwas klarer zu machen, stell dir vor B.Foo() waere wie folgt definiert:


    public new void Foo( int integer ) 
    {
      // ...
    }

Nun brauchen wir uns nicht mehr zu fragen, welche Funktion besser passt, die Problematik bleibt aber bestehen.

Wie kann ich nun von C aus auf A.Foo() zugreifen? Mein zweiter Loesungsvorschlag wuerde fuer dieses Problem nun nicht mehr funktionieren.

Das Problem ergibt sich, wenn A eine Fremdklasse ist, die Foo(int) noch nicht enthaelt, ich eine Klasse B mit Foo(int) erstelle und dann spaeter in A Foo() hinzugefuegt wird.

  • Rene
18.02.2005 - 16:21 Uhr

Nein, leider nicht, habe ich zuerst auch gedacht. Selbst in der Foo() Funktion von B muss ich das Schluesselwort base verwenden, weil die Funktion sich sonst selbst aufruft. Hier passt die Funktion Foo aus A auch besser zu int als die Funktion Foo aus B.

Ich denke mal, dass der Compiler zuerst in der eigenen Klasse und dann Schritt fuer Schritt in der Klassenhierarchie nach einer passenden Funktion sucht. Deshalb wird Foo() aus B dem Foo aus A bevorzugt. Denn eine Funktion welche System.Object erwartet passt auch, wenn ein int reingegeben wird.

  • Rene
18.02.2005 - 14:50 Uhr

Hi!

Ich habe folgende Klassenhirarchie gegeben:


  public class A
  {
    protected void Foo( int integer ) { }
  }

  public class B : A
  {
    public void Foo( object obj ) 
    {
      int integer = ObjectToInt( obj );
      base.Foo( 3 );
    }

    private int ObjectToInt( object obj )
    {
      return 3;
    }
  }

  public class C : B
  {
    public void DoSomething()
    {
      Foo( 7 );
    }
  }

Ich möchte nun auf die Methoden der Basisklassen zugreifen, d.h. von Klasse B auf Methoden von Klasse A und von Klasse C auf Methoden der Klassen A und B. Auf Methoden der direkten Basisklasse kann leicht mittels dem Schluesselwort base zugegriffen werden. Ein Problem habe ich nun, wenn ich auf eine Methode einer indirekten Basisklasse zugreifen möchte, also von Klasse C aus auf die Methode Foo() der Klasse A.

Da die Methode Foo() in der Klasse B überladen wird und ein int auf ein System.Object gecasted werden kann, wird beim Aufruf von Foo in C die Methode Foo in B aufgerufen. Ich möchte aber Foo in A aufrufen.

Meine Ideen bislang:

  1. Casten der Klasse C auf Klasse A:

A a = (A)this;

Dies funktioniert nicht, da Foo() in A protected ist.

  1. Delegation der Methode Foo() von B nach A:

Füge in B folgende Funktion hinzu:


public void Foo( int integer )
{
  base.Foo( integer );
}

Dies funktioniert, da int besser zu int passt als zu System.Object.

Was macht man aber, wenn A und B Fremdklassen sind, welche diese Delegationsfunktion nicht enthalten? Von den Rechten her (B ist public und Foo in A ist protected) hat man in C das Recht auf Foo in A zuzugreifen. In C++ wuerde man einfach A::Foo(3) schreiben.

Gibts eine analoge Möglichkeit in C#?

  • Rene
16.02.2005 - 12:10 Uhr

Hallo!

Ich habe ein Objekt vom Typ PropertyInfo gegeben:


PropertyInfo property;

Gibt es eine Möglichkeit aus property die zugehörige Instanz zu gewinnen, also die Instanz, welche diese Eigenschaft einhält?

Danke!

  • Rene
11.02.2005 - 16:22 Uhr

Es geht mir nicht speziell um die STL, sondern im generellen um Klassenbibliotheken, die auf Templates basieren. Ich möchte beispielsweise Teile von Boost einsetzen, hier zeigen sich aber ähnliche Probleme wie bei der STL. Die Problematik lässt sich aber einfacher an der STL zeigen, deshalb habe ich dieses Beispiel gewählt.

11.02.2005 - 14:42 Uhr

Hallo!

Ich suche nach einer Möglichkeit in ManagedC++ die STL mit .NET-Klassen zu verwenden. Beispielsweise könnte man einen vector von System.String anlegen:


vector<System::String> vec;

Dies liefert die Fehlermeldung:
C3149: 'SystemString': Ungültige Verwendung des verwalteten Typs 'SystemString'; haben Sie eine '*' vergessen?

Verwendet man stattdessen


vector<System::String*> vec;

erhält man die Fehlermeldung:
C2440: '=': 'SystemString __gc *__gc * ' kann nicht in 'SystemString __gc ** ' konvertiert werden

Hat dies schonmal jemand probiert und erfolgreich eingesetzt?

  • Rene
02.02.2005 - 13:38 Uhr

Wandel den int doch einfach in einen string um und ueberpruefe die Laenge des strings:


int myInt = 4711;
string text = myInt.ToString();
if ( text.Length < 5 )
{

}

02.02.2005 - 12:42 Uhr

Versuchs mal hiermit:

Type type = typeof(Klasse1);
Type typeInterface = type.GetInterface("IInterface", true);
if ( typeInterface != null ) // Klasse1 implements IInterface
{

}

02.02.2005 - 10:18 Uhr

Hi herbivore,

ja, zum einen soll ein Plugin ein uebergebenes Objekt nicht veraendern. Zum anderen soll ein Plugin an Funktionen in meinem Code uebergeben werden, wobei das Plugin nicht geaendert werden darf.

Zu 1) Klar

Zu 2) Hier ist das Problem, dass das Erstellen der Kopie Performance und Speicherplatz kostet. Insbesondere wenn die Objekte sehr gross sind und Verweise auf andere Objekte enthalten.

Es scheint wohl keine Loesung wie in c++ mit const zu geben. Ich werde mich wohl fuer das bessere Uebel entscheiden muessen.

  • Rene
02.02.2005 - 09:53 Uhr

VizOne,

dies hoert sich schon ganz gut an. Nun muss aber jeder, der ein Plugin schreiben will zwei Klassen implementieren, z.B. Person und ReadOnlyPerson. Dies ist fuer einen Pluginschreiber ein erheblicher Mehraufwand und ein Plugin soll ja gerade einfach zu implementieren sein.

Des Weiteren sehe ich das Problem die beiden Klassen konsistent zu halten, insbesondere wenn die Klassen groesser sind und noch häufig verändert werden. Hier ist ein grosses Fehlerpotential gegeben.

Aufgrund der genannten Probleme sollte man vielleicht ueberlegen, das Problem in die Dokumentation zu verlagern. So muss jemand der eine Funktion implementiert selbst darauf achten, dass er Eingabeparameter nicht verändert. Die Fehleranfaelligkeit ist zwar weiterhin gegeben, aber der Mehraufwand beim Pluginschreiben wird reduziert.

01.02.2005 - 17:24 Uhr

@norman_timo:

Bei deinem ersten Vorschlag sehe ich das Problem, dass man bei einem Property schnell vergisst, die entsprechende Abfrage hinzuschreiben. Insbesondere wenn mehrere Klassen readonly anbieten sollen (bei mir sollen fast alle Klassen die Möglichkeit des readonly bieten). Diese Methode bedeutet einen erheblichen Mehraufwand und ist fehleranfaellig. Und die Fehleranfaelligkeit meines Codes versuche ich durch readonly ja gerade zu verhindern. Gut finde ich, dass man ueber das Attribut steuern kann, ob die Klasse schreibzugriff hat oder nicht. Denn diese Anforderung habe ich.

Der zweite Vorschlag erfuellt diese Anforderung leider nicht. Eine Klasse waere dann nur readonly.

@Xqgene:

Hoert sich schon ganz gut an. Ich moechte aber Plugins schreiben, wobei die Plugins eine variable Anzahl an Properties haben. Und der Interfaceansatz setzt eine statische (also zur Compilezeit bekannte) Anzahl an Properties voraus. Man koennte natuerlich sagen, dass man eine Maximalanzahl an Properties in das Interface setzt. Diese Anzahl muss(!) dann aber auch von jedem Plugin implementiert werden. Und es ist schon bloed, sagen wir 10 Properties zu implementieren wobei nur 2 benoetigt werden und die restlichen 8 nur Dummies sind.

Es muss doch eine Moeglichkeit, wie in c++ durch const, geben einem Objekt einfach die Schreibrechte zu entziehen.

Euch beiden trotzdem vielen Dank, vielleicht faellt ja einem nochwas ein.

01.02.2005 - 13:56 Uhr

Xqgene,

mir ist nicht klar was du damit meinst.
Kannst du evtl. ein Beispiel bringen?

Ich habe noch etwas rumgesucht und bzgl. JAVA folgendes gefunden: Finale Referenzen

In Java gibt es also keine Möglichkeit konstante Objektreferenzen an Funktionen zu übergeben. Zumindest können in JAVA Werttypen mit "final" konstant gemacht werden.
Wie schauts in C# aus?