Laden...
U
Benutzerbeschreibung

Forenbeiträge von Uwe81 Ingesamt 282 Beiträge

05.09.2018 - 23:00 Uhr

Hallo,

Ich habe ein Array von Enumerables


IEnumerable<T>[] sources;

Typischerweise iterieren diese Enumerables nicht schnell, sind z.B. Dateien aus einem Document Management System. Der Overhead ist hoch, sodass sich wegen der hohen Latenz Parallelisierung lohnen würde, z.B. weil ich bei drei verschiedenen Repositories Dokumente runterlade.

Das Interface gibt mir für ein Repository alle Dokumente als IEnumerable<T>

Jetzt suche ich ein Enumerable, was sich wiefolgt berechnet.
Für jedes Sourceelement gibt es einen kleinen Buffer.
Die Enumerables werden parallel durchlaufen, d.h. wenn der Buffer für ein Enumerable nicht mehr gefüllt ist, wird das nächste Element bereits abgerufen.
Wenn ich für das "merged Enumerable" das nächste Element abfrage, erhalte ich irgend eines aus den buffern der unterliegenen enumerables, oder halt das nächste was da ist.

Ich bin neun in Tasks, PLINQ und parallel foreach. Daher verliere ich mich bei der Implementierung.

Das beste was ich bisher hinbekommen habe ist eine manuelle Implementierung mit Blocking Collections (noch nicht getestet)
Geht das wirklich nicht eleganter?


        public int MaxCapacity { get; set; }
        public IList<IIterateStrategy> IterateStrategies { get; set; };

        public IEnumerable<DSDownloadEntry> Iterate() {
            var collection = new BlockingCollection<DSDownloadEntry>(MaxCapacity);
            var tasks = new Task[IterateStrategies.Count];
            for(int i = 0; i<IterateStrategies.Count; i++) {
                int index = i;
                var strategy = IterateStrategies[index];
                tasks[i] = Task.Factory.StartNew(() => {
                    foreach (var item in IterateStrategies[index].Iterate()) {
                        collection.Add(new DSDownloadEntry() { Container = item });
                    }
                });
            }
            Task.Factory.ContinueWhenAll(tasks, _ => collection.CompleteAdding());
            return collection.GetConsumingEnumerable();
        }

Ergänzung:

Ich habe jetzt nochmal PLINQ versucht:


    class Producer {
        public string Prefix;
        public int Count;

        public IEnumerable<string> GetResults() {
            Random random = new Random();
            for (int i = 0; i < Count; i++) {
                var text = string.Format("{0}{1:000000}", Prefix, i);
                Console.WriteLine("Producing " + text);
                yield return text;
            }
            Console.WriteLine("############### DONE " + Prefix);
        }
    }
    class Program {
        public static void Main() {
            var producers = new[] {
                new Producer() {Prefix = "A", Count = 100000},
                new Producer() {Prefix = "B", Count = 100000},
                new Producer() {Prefix = "C", Count = 100000},
            };

            var merged = from p in producers.AsParallel()
                         from r in p.GetResults()
                         select r;

            foreach (var r in merged) {
                Console.WriteLine("Consumint " + r);
            }
        }
    }

Das Problem hier ist, das der Producer bereits weiterläuft, auch wenn nur wenig abgerufen wird.
Eine ergänzung "AsParallel().WithMergeOptions" hat nichts verändert.

Mein Wunsch wäre eben, dass pro Producer nur wenige Einträge gebuffert werden.

13.03.2015 - 23:54 Uhr

Wenn ich die Anwendung selbst in der Hand hätte, würde ich die Assembly-Aufteilung auch nicht so machen.

So ist es aber, dass die Anwendung meinen Code per COM-Schnittstelle aufruft, ich dann meinerseits eine Methode aufrufe, die mein Control erzeugt und in einem vorgegebenen Rahmen anzeigt. Dabei müssen die Assemblies aber an unterschiedlichen Stellen liegen, insbesondere das Control in einem bestimmten Unterordner des Programms.

Jetzt habe ich es erstmal so gelöst, dass ich mir per Reflection das Command als ICommand hole.

Sollten noch weitere Abhängigkeiten entstehen, muss ich das nochmals überdenken. Allerdings weiß ich garnicht so genau, wo dann das gemeinsam bekannte Interface-Assembly liegen soll. Im Ordner der View? Im Ordner der Logik (die per COM-Interface angestoßen wird).

13.03.2015 - 09:32 Uhr

Hallo!

Ich programmiere gerade ein WPF UserControl, welches in einer fremden Anwendung eingebunden werden soll.

Aus den Anforderungen der Anwendung hat sich folgende Architektur ergeben:
Ein Assembly, welches die BL und das ViewModel beinhaltet.
Ein Assembly, welches das Control beinhaltet.
(ich weiß, dass man BL und ViewModel lieber trennen würde, da aber beides aus 3 bis 6 kleinen Klassen besteht, tut mir das nicht wirklich weh).

Für die Anwendung ist es vorteilhaft, dass die beiden Assemblies sich nicht referenzieren. Soweit funktioniert das auch alles gut.

Das Problem ist nun folgendes:
Mein Control muss ein interface implementieren, welches (z.B.) so aussieht:


interface IApplicationControl {
  public void OnCanExecute(CanExecuteRoutedEventArgs e) { }
  public void OnExecuted(ExecutedRoutedEventArgs e) { }
}

In den EventArgs steht dann jeweils über die OriginalSource der Name des Buttons.

Jetzt würde ich gerne an dieser Stelle quasi ein Command aus dem ViewModel fragen nach CanExecute bzw. in die Execute aufrufen. Also


class MyViewModel {
  public ICommand OkCommand {get; private set;}
}

class MyControl : IApplicationControl {
  public void OnCanExecute(CanExecuteRoutedEventArgs e) { 
    
    if (e.OriginalSource.Name == "Ok"){
        MyViewModel viewModel = DataContext as MyViewModel; //GEHT NICHT!!
        e.CanExecute = viewModel.OkCommand.CanExecute(null);
    }
  }
}

Aber ich kann den DataContext ja nicht auf das spezifische ViewModel casten, weil ich keine Referenz auf das Assembly habe.

Gibt es nun einen "eleganten" Weg, dass ich mir in XAML dieses Command über DataBinding hole, oder muss ich das im CodeBehind über Reflection machen?

Vielen Dank!

11.03.2015 - 22:29 Uhr

Statische Methoden sind solange praktisch, solange du nicht versuchst threads zu verwenden, dann kann es knifflig werden.

Das ist so falsch. Das Problem tritt bei statischen Variablen auf. Gegen Statische Methoden, welche nur Parameter und lokale Variablen haben, spricht nichts. Im gegenteil halte ich das für eine sehr einfache Möglichkeit, Threadsicherheit zu erreichen.

Ist dann zwar quasi prozedurale Programmierung als OOP, aber wenn es zum Problem passt (mathematische Algorithmen o.Ä.) völlig OK.

Es ist sogar so, dass - wenn ich ein Objekt habe, welches einen Algorithmus durchführt und dabei seinen inneren Zustand temporär verändert - ich sehr gerne statische Hilfsmethoden schreibe die eine Instanz erzeugen, den Algorithmus ausführen, die Instanz wegwerfen und das Ergebniss zurückgeben. Quasi um Threadsicherheit zu garantieren.

Zusammenfassend zum Thema Threads:
Trivial threadsicher sind Methoden, die nur Parameter und Lokale Variablen verwenden.

Gefährlich sind immer äußere Zustände. Bei normalen Objekten kann mann dann verschiedene Instanzen anlegen, bei statischen, nicht readonly Variablen hat man ein Problem.....

22.12.2014 - 23:19 Uhr

Getter und Setter verletzen das OOP-Prinzip genauso wie get und set Methoden. Also erstmal garnicht, bei extensivem gebrauch bekommt das ganze aber einen Geschmack.

Du kannst in einem Getter etwas berechnen, also nur weil es ein Getter gibt muss dahinter noch lange kein Feld stehen. Insofern Kapselt ein Getter. Auch ein Setter muss nicht unmittelbar in ein Feld schreiben, könnte also z.B. einen Setter von einem privaten Objekt aufrufen.

Insofern kapseln sowohl Getter und Setter die Implementierung, sind daher guter OOP-Stil.

Ein Problem wird das ganze dann, wenn man - weil es ja so schön einfach ist - aus jedem privaten Feld ein Property macht ung {get; set;} dahinter schreibt. Dann verletzt man die OOP-Prinzipien.

Generell gilt für alles, was public ist: So viel wie nötig, so wenig wie möglich. Das gilt auch für Properties.

03.12.2014 - 23:43 Uhr

Ich finde immernoch, dass die meisten Argumente eigentlich den Kern des Problems nicht treffen.

Die abstrakte Basisklasse ist ein Implementierungsdetail, was nach außen nicht bekannt ist. Ich kann es jederzeit ändern.

Wenn nun 8 Klassen von dieser Basisklasse ableiten, für eine neunte passt es nicht mehr, dann implementiere ich halt das Interface direkt. Wenn ich eine Klasse erweitern will und die Basisklasse nicht mehr passt, dann implementiere ich das Interface direkt oder erbe gar von einer anderen Basisklasse.

In all diesen Fällen bekommen die Benutzer des Interfaces das garnicht mit, weil die Entkopplung eben über das Interface stattfindet. Die Basisklasse entspricht eher einer "privaten Vererbung" aus dem C++-Umfeld.

Daher würde ich das weiterhin machen und mich um ggf. auftretende Probleme erst später kümmern. Denn Probleme mit einer Klasse in dieser Architektur können nur dann auftreten, wenn sich die Aufgaben dieser Klasse ändern. Dann muss ich sie sowieso anfassen. Und die Entkopplung zu den Verwendungen der Klasse bleibt durch das Interface unverändert.

03.12.2014 - 14:04 Uhr

Ich finde das Konzet eigentlich sehr sauber, verwende es selbst sehr gerne.
Du musst nur sicherstellen, dass die Nutzer sich eben nur auf das generelle Interface verlassen und nicht auf Implementierungsdetails der abstrakten Klasse.

Die Seperation of Concerns:* Interface stellt das nach außen verbindliche Interface dar.

  • Abstrakte Klasse vermeidet Redundanzen in der Implementierung.

Die abstrake Basisklasse bleibt ein Implementierungsdetail, was du jederzeit entfernen könntest ohne dass die Anwendenden Klassen etwas davon mitbekommen.

Ich halte das Konzept sogar eher für eine Best Practice.

05.07.2013 - 09:16 Uhr

Hallo!

Bisher habe ich reichlich Erfahrungen mit GUI-lastigen Desktop-Anwendungen, werden nun aber eine Client/Server-Anwendung entwickeln müssen. Während sich für einige Bereiche mein Bild schon geschärft hat, stocher ich in anderen Ecken noch im Nebel...

Folgendes (fiktives, aber dem Problem nahe kommendes) Szenario.

In einer Universität teilen sich drei Fachbereiche ein Gebäude. Jeder Fachbereich hat im Wesentlichen seine eigenen Räume, aber einige große Hörsäle werden auch gemeinsam genutzt. Es soll nun eine Software entwickelt werden, um die Vorlesungen zu planen. Außerdem sollen Studenten per Internet / Mobile App sich zu anmelde-beschränkten Kursen und / oder Übungen anmelden zu können.

Es gibt folgende Komponenten:*Pro Fachbereich einen lokal installierten Planungs-Client, mit dem die Vorlesungen dieses Fachbereichs geplant werden können. Da dieses durch Optimierungsalgorithmen unterstützt wird und recht komplexe Interaktionen benötigt, ist eine Implementierung als HTML im Browser nicht sinnvoll. *Einen zentralen Server, auf dem der aktuelle Plan gespeichert ist und mit dem die Planungs-Clients kommunizieren. U.A. muss es z.B. möglich sein, dass ein Planungs-Client einen gemeinsam genutzten Hörsaal für einen gewissen Zeitraum sperrt, um in diesem umzuplanen (Pessimistic Locking). Dieses sollte dann allen anderen Clients instantan angezeigt werden (also muss Push vom Server zum Client gehen). *Es kann notwendig sein, dass Client und Server nur über Internet verbunden sind, also die Server-Schnittstelle im Internet steht (Sicherheit ist also wichtig). *Es gibt eine Website bzw. diverse Mobile Apps, mit denen Studenten sich zu Übungen / Vorlesungen anmelden können bzw. den vorläufigen Plan sehen. *Es soll möglich sein, den Studenten Änderungen für angemeldete Kurse per Push-Nachricht zu senden.

Wie gesagt, das Beispiel ist fiktiv, kommt aber unserem Praktischen Problem recht nahe und ich muss jetzt nicht einen Roman zur Erläuterung der realen Anwendung schreiben.

Folgende Design-Entscheidungen habe ich bisher getroffen: *Die Mobile Apps werden mit HTML5 erstellt, um nicht für iOS/Android/Windows entwickeln zu müssen. *Die Kommunikation des Servers zu den Mobile Apps und der Studenten-Website soll über eine REST-Schnittstelle erfolgen. Mir gefällt dafür NancyFX recht gut, zumal ich mit einem ähnlichen Micro-Framework privat schon gute Erfahrungen gemacht habe (Slim unter PHP, obwohl ich ansonsten PHP hasse.....) *Ob die Website eine Single Page Application wird oder ich immer den RoundTrip über den Server gehe und HTML ausliefere, weiß ich noch nicht. Haber aber ein ganz gutes gefühl für die Trade Offs *Der Planungs-Client wird eine WPF-Desktopanwendung. Diese wird immer zusammen mit dem Server entwickelt, es gibt nur wenige lokale Installationen und der Komfort währen der Planung ist wichtiger als das Rollout. *Authentifizierung vermutlich mittels JSON Web Token.

Bei folgendem Punkt bin ich etwas verloren: *Wie mache ich bei der Schnittstelle zu den Apps die Push-Nachricht? Ist SignalR dort eine gute Wahl? Quasi dass man als Message sendet "Es gibt was neues, fordere mal folgende Ressourcen an" und dann einen Link mit sendet.

*Welche Kommunikation zwischen Planungs-Client und Server verwende ich? Die sind eng gekoppelt, müssen niemals an andere Systeme angebunden werden und werden immer zusammen entwickelt. Die Kommunikation kann aber evtl. über Internet stattfinden, sollte also sicher sein.
--> Mir erschien WCF das Mittel der Wahl, habe aber jetzt viele Warnungen gehört, dass es sehr komplex sei.
--> Eine REST-Schnittstelle ist eine sehr lose Kopplung. Ist diese nicht hier zu Aufwändig und zu viel Overhead? Zumal dann die Push-Problematik dann nicht gelöst ist, oder auch SignalR?
--> Remoting wirkt einfacher, soll aber wohl veraltet sein und nur noch aus Kompatibilitätsgründen mitgeliefert werden. Aber für ein neues Projekt
--> TCP/IP Sockets: Ist halt sehr low level, dafür versteht man vermutlich, was man tut. Aber bekommt man als Netzwerk-Anfänger wirklich die Probleme in den Griff
--> Eine Messaging Infrastruktur (MSMQ). Aber brauchen wir wirklich Messaging? Gefühlt ist das eher das klassische RPC?

Insbesondere der letzte Punkt ist derzeit schwierig. Es gibt diverse Möglichkeiten, mir sind die Tradeoffs aber nicht klar. Gibt es dazu Meinungen, Tipps oder evtl. sogar Hinweise zu Tutorials / Büchern, wo die verschiedenen Technologien verglichen werden und Guidelines, wann man welche nimmt?

Vielen Dank für Tipps,
Uwe

11.10.2012 - 21:25 Uhr

Stimmt, im allgemeinen führt das vermutlich zu Problemen.

Da ich die Kombination von IFoo und IBar ja im voraus kenne, habe ich nun einfach ExtensionsMethods geschrieben.


static void RegisterBar<TBar>() where TBar:IBar {
    builder.Register<IBar, Bar>();
    builder.Register<IFoo, Bar>();
}

Irgendwie habe ich erst versucht, das über ein RegistrationModule zu machen, aber da das später immer im Code konfiguriert wird, kann ich es eigentlich auch direkt per EtensionMethod machen (dennoch ist es interessant, RegistrationModules zu kennen).

Vielen Dank für den Fingerzeig in die richtige Richtung,
Uwe

11.10.2012 - 10:25 Uhr

Hallo, der Titel ist etwas blöd, aber in Code ist es leicht zu erklären, was ich suche...


using LightCore;

interface IFoo {
    void DoFoo();
}

interface IBar : IFoo {
    void DoBar();
}

class Bar : IBar {
    public void DoFoo() {}
    public void DoBar() {}
}

class Program {
    public static void Main() {
        var builder = new ContainerBuilder();
        builder.Register<IBar, Bar>();
        var container = builder.Build();
        var foo = container.Resolve<IFoo>();
    }
}

Bei der letzten Zeile fliegt eine Exception. Ist auch klar, weil kein IFoo registriert ist. Allerdings kennt der Container ja ein IBar und weiß, dass das auch ein IFoo ist. Gibt es eine Möglichkeit, dass das automatisch aufgelöst wird?

Was geht (mir aber nicht so gut gefällt) ist


builder.Register<IBar, Bar>();
builder.Register<IFoo, Bar>();

oder


builder.Register<IBar, Bar>();
builder.Register<IFoo>(c => c.Resolve<IBar>());

Mir ist das ganze deshalb wichtig, weil ich ein Framwork entwickel, welches dann von anderen verwendet wird. Innerhalb des Framworks will ich (aus Kapeselungsgründen) möglichst spezialisierte Interfaces durch die Gegend reichen, nach außen will ich aber für den Benutzer meines Frameworks die Konfiguration des DI Containers möglichst einfach halten.

Viele Grüße und vielen Dank,
Uwe

11.06.2012 - 22:57 Uhr

Hallo!

Ich habe das Programm (ThinkPad T410s) bisher nur auf meinem Rechner laufen lassen, kann also einen Fehler im Grafiktreiber nicht ausschließen. Die Benutzerkontensteuerung (musste erst nachschauen, was UAC ist...) habe ich aktiviert, wäre auch eine Idee...

Ich versuche mal ein Minimalbeispiel zu konstruieren, in dem der Fehler auftritt. Habe aber aus diversen Gründen derzeit quasi keine Zeit mehr, werde mich dann in ein oder zwei Wochen nochmal melden...

Schonmal vielen Dank für die Ideen.

Viele Grüße,
Uwe

05.06.2012 - 23:04 Uhr

Nein, der Titel ist nicht irreführend. Und ja, ich bin immernoch etwas fassungslos...

Ich habe reproduzierbar folgendes Problem:
Ein eigenes kompliziertes WinForms-UserControl, welches eine ComboBox beinhaltet. Dieses ist eingebunden in eine WPF-Form.

Wenn ich mit der Maus über die WinForms-ComboBox komme, geht kurz der Bildschirm aus (so als wenn man einen externen Monitor / Beamer anschließt und der Rechner versucht, seine Auflösung anzupassen). Bewegte ich die Maus in der ComboBox ist alles ok, solange bis ich die Maus aus der ComboBox rausbewege, dann tritt dasselbe Problem auf.

Das Problem ist unabhängig von Externer Monitor angeschlossen (digial oder analog oder nur Laptop), und Benutzung der Maus oder des Touch-Pads.

Ich hatte dasselbe Control (intern mit etwas anderem Docking/Anchor/AutoSize) auch schon vorher in WPF und es lief einwandfrei...

Da ich perspektivisch die Form eh auf WinForms migrieren soll (soll in eine WinForms-Anwendung eingebaut werden und dann lohnt WPF nur für das Fenster nicht mehr) lässt sich das Problem für mich leicht umgehen.

Aber aus Interesse: Hat schonmal jemand ähnliches gehabt?

Viele Grüße,
Uwe

13.04.2012 - 15:35 Uhr

Also IMHO wird es falsch, wenn Model-Klassen gegenseitig auf INotifyPropertyChanged hören müssen und dann anhand des Strings erkennen, Was sich nun geändert hat.

Daher habe ich folgende Fausregel:
Existiert eine komplexe Domain Logic, dann sollte das Modell möglichst sauber sein und kein INotifyPropertyChanged implementieren.

Ist die Anwendung eine eher dünne Aufbereitung von Daten ohne komplizierte Domain-Logic, spare ich mir das doppeln aller Daten in Model und ViewModel, implementiere im Model das INotifyPropertyChanged und implementiere nur dann ViewModel-Klassen, wenn diese über das Model hinausgehende Daten halten müssen.

19.03.2012 - 10:04 Uhr

Habe gerade noch folgenden Link gefunden:
Applying aspects to 3rd party assemblies using PostSharp

19.03.2012 - 09:55 Uhr

Hallo!

Ich habe eine komplexere GUI-Komponente entwickelt, die bei uns im Haus oft verwendet wird. Leider treten dort auch manchmal Fehler auf, so dass ich gerne mittels Tracing den Ablauf vor Auftreten des Fehlers feststellen möchte.

Um nicht den ganzen Code zu verschmutzen, dachte ich, dass sei ein gutes Anwendungsfeld für PostSharp (meine erste Berührung mit AOP).

Wir arbeiten bei uns an unterschiedlichsten Projekten und haben unterschiedliche, frei konfigurierbare Entwicklungsumgebungen. Insbesondere wird sicherlich nicht jeder, der meine Komponente verwendet, PostSharp installieren wollen. Auch ist dieses Logging nicht überall sinnvoll.

Daher meine Frage: Kann man sowas in der Art gestalten, dass es z.B. 3 Projekte/Assemblies gibt:

MyLib.Core
MyLib.UnitTest
MyLib.Aspects

Leute, die das ganze verwenden, brauchen nur MyLib.Core (was idealerweise auch so übersetzbar ist)
Als Entwickler habe ich halt noch die UnitTests (und dementsprechend eine Abhängigkeit auf NUnit) und die Aspects (und die Abhängigkeit auf PostSharp).

Bei UnitTests funktioniert das gut: Der eigentliche Produktivcode weiß nichts, über deren Existenz. Bei den Aspects mit PostSharp habe ich vergleichbares nicht hinbekommen.

Was ich möchte: MyLib.Core soll über PostSharp nichts wissen und ohne PostSharp funktionsfähig kompilierbar sein. Aber ich möchte in einem zusätzlichen Build-Step (oder einer anderen Build-Konfiguration) die Möglichkeit haben Logging mittels PostSharp einzuweben.

Geht sowas? Ist AOP der falsche Ansatz?

Viele Grüße,
Uwe

09.02.2012 - 16:53 Uhr

Ich glaube, das geht kürzer (single threaded Anwendung mit .NET 3.5);


int _value;

public int Value {
    get 
    {
        lock(this)
        {
            try
            {
                return _value;
            }
            catch(Exception ex)
            {
                throw ex;
            }
        }
    }
}

22.09.2011 - 10:33 Uhr

Hallo!

Ich habe mir für ein WPF DataGrid ein DataTemplate für die Columns erstellt. Jetzt möchte ich für zwei Properties CustomA und CustomB eine DataGridTemplateColumn mit diesem Template anwenden.

Allerdings kann ich irgendwie dem Template keine DataSource mitgebe, d.h. ich muss im Template selbst schon an CustomA oder CustomB binden (und kann nicht relativ dazu anfangen).

Ich vermute, dass ich als neuling, da ein Teil des Konzepts noch nicht verstehe.

PS: Ich nutze aus verschiedenen Gründen noch das WpfToolkit und .NET 3.5

Vielen Dank,
Uwe

07.09.2011 - 14:29 Uhr

Die GetHashCode-Methode von Structs ist IMO standardmäßig Fehlerhaft:

Aus ValueType.cs


        /*=================================GetHashCode==================================
        **Action: Our algorithm for returning the hashcode is a little bit complex.  We look
        **        for the first non-static field and get it's hashcode.  If the type has no
        **        non-static fields, we return the hashcode of the type.  We can't take the 
        **        hashcode of a static member because if that member is of the same type as
        **        the original type, we'll end up in an infinite loop. 
        **Returns: The hashcode for the type. 
        **Arguments: None.
        **Exceptions: None. 
        ==============================================================================*/

Der Kommentar ist aber falsch. Eine Korrektur steht in Why is ValueType.GetHashCode() implemented like it is?

The actual implementation of ValueType.GetHashCode() doesn't quite match the comment. It has two versions of the algorithm, fast and slow. It first checks if the struct contains any members of a reference type and if there is any padding between the fields. Padding is empty space in a structure value, created when the JIT compiler aligns the fields. There's padding in a struct that contains bool and int (3 bytes) but no padding when it contains int and int, they fit snugly together.

Without a reference and without padding, it can do the fast version since every bit in the structure value is a bit that belongs to a field value. It simply xors 4 bytes at a time. You'll get a 'good' hash code that considers all the members. Many simple structure types in the .NET framework behave this way, like Point and Size.

Failing that test, it does the slow version, the moral equivalent of reflection. That's what you get, your KeyValuePair<> contains references. And this one only checks the first candidate field, like the comment says. This is surely a perf optimization, avoiding burning too much time.

Dieser Kommentar wirkt plausibel, wie folgendes Beispiel zeigt:


using System;

struct MyObjStruct {
    public object x;
    public object y;
}

struct MyIntStruct {
    public long x;
    public long y;
}


public class Program {
    static object x = new object();
    static object y1 = new object();
    static object y2 = new object();

    public static void Main() {
        var os1 = new MyIntStruct { x = 1, y = 3 };
        var os2 = new MyIntStruct { x = 1, y = 4 };
        Console.WriteLine(os1.GetHashCode() == os2.GetHashCode()); //False

        var is1 = new MyObjStruct { x = x, y = y1 };
        var is2 = new MyObjStruct { x = x, y = y2 };
        Console.WriteLine(is1.GetHashCode() == is2.GetHashCode()); //True
    }
}

Nun schauen wir uns mal die Equals-Methode aus ValueType.cs an


        public override bool Equals (Object obj) { 
            BCLDebug.Perf(false, "ValueType::Equals is not fast.  "+this.GetType().FullName+" should override Equals(Object)"); 
            if (null==obj) {
                return false; 
            }
            RuntimeType thisType = (RuntimeType)this.GetType();
            RuntimeType thatType = (RuntimeType)obj.GetType();
 
            if (thatType!=thisType) {
                return false; 
            } 

            Object thisObj = (Object)this; 
            Object thisResult, thatResult;

            // if there are no GC references in this object we can avoid reflection
            // and do a fast memcmp 
            if (CanCompareBits(this))
                return FastEqualsCheck(thisObj, obj); 
 
            FieldInfo[] thisFields = thisType.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
 
            for (int i=0; i<thisFields.Length; i++) {
                thisResult = ((RtFieldInfo)thisFields[i]).InternalGetValue(thisObj,false);
                thatResult = ((RtFieldInfo)thisFields[i]).InternalGetValue(obj, false);
 
                if (thisResult == null) {
                    if (thatResult != null) 
                        return false; 
                }
                else 
                if (!thisResult.Equals(thatResult)) {
                    return false;
                }
            } 

            return true; 
        } 

Fazit: Sind alle Member ValueTypen und können ohne Padding aligned werden, dann wird sowohl für Equals als auch für GetHashCode das Bitmuster verwendet. Ansonsten werden die GetHashCode() des ersten Member und die Equals() aller Member aufgerufen.

Testen wir das:


using System;


struct MyDifference {
    public int x;
    public int y;

    public override bool Equals(object obj) {
        if (!(obj is MyDifference)) return false;
        var other = (MyDifference) obj;
        return x - y == other.x - other.y;
    }

    public override int GetHashCode() {
        return x - y;
    }
}



struct MyObjStruct {
    public MyDifference x;
    public object y;
}



struct MyLongStruct {
    public MyDifference x;
    public long y;
}



public class Program {
    public static void Main() {
        var y = new object();

        var md1 = new MyDifference {x = 5, y = 2};
        var md2 = new MyDifference {x = 6, y = 3};
        Console.WriteLine("Equals myDiff: " + md1.Equals(md2));
        Console.WriteLine("HashCd myDiff: " + (md1.GetHashCode() == md2.GetHashCode()));

        var os1 = new MyObjStruct {x = md1, y = y};
        var os2 = new MyObjStruct {x = md2, y = y};
        Console.WriteLine("Equals objStruct: " + os1.Equals(os2));
        Console.WriteLine("HashCd objStruct: " + (os1.GetHashCode() == os2.GetHashCode()));

        var ls1 = new MyLongStruct {x = md1, y = 9};
        var ls2 = new MyLongStruct {x = md2, y = 9};
        Console.WriteLine("Equals longStruct: " + ls1.Equals(ls2));
        Console.WriteLine("HashCd longStruct: " + (ls1.GetHashCode() == ls2.GetHashCode()));
    }
}

Zu erwarten:
Für die MyDifference müsste beides True ergeben.

Für die MyObjStruct müsste per Reflection sowohl Equals als auch GetHashCode (für das erste Feld) aufgerufen werden, also beide male True ausgegeben werden.

Für die MyLongStruct müssten die Bitmuster verwendet werden (also weder GetHachCode noch Equals aufgerufen werden), und beide male False ausgegeben werden.

Die Ausgabe ist aber


Equals myDiff: True
HashCd myDiff: True
Equals objStruct: True
HashCd objStruct: False
Equals longStruct: True
HashCd longStruct: False

Also ist, obwohl MyDiff eine valide GetHashCode und Equals anbietet, die Implementierung von GetHashCode sowohl für MyObjStruct als auch für MyLongStruct falsch, weil Equals True ergibt und GetHashCode false ist.

Im Debugger sieht mann, dass sowohl by MyObjStruct.Equals() als auch bei MyLongStruct.Equals() die MyDifference.Equals() aufgerufen wird, hingegen in keinem der GetHashCodes die GetHashCode der MyDifference.

Ich habe das auf Win7 64 bit, Vs2010 kompiliert als .NET 4.0;

Das Ergbnis ändert sich nicht, wenn man im MyLongStruct das y durch ein int ersetzt. Es ist sowohl für int y als auch für long y unabhängig vom Kompilieren als x64 oder x86.

Auch das steht eigentlich in StackOverflow

One more excruciating detail: the fast version has a bug that bytes when the structure contains a field of a type decimal. The values 12m and 12.0m are logically equal but they don't have the same bit pattern. GetHashCode() will say that they are not equal.

06.09.2011 - 19:56 Uhr

Also ein C-Programm mit .NET und der C++ Redistributable......

Welche Sprache habt ihr denn nun verwendet? C#, C++ oder C? Oder eine Mischung?
Bei C# werdet ihr .NET brauchen, bei C++ oder C könnte das Redistributable helfen.

Ein beliebter Fehler ist es, bei C oder C++ gegen die Debug-Version zu linken, dann nützt das Redistributable nichts, sondern man braucht gleich Visual Studio

Ansonsten könnte im Ereignismonitor von Windows ein Hinweis stehen.

Mehr gibt meine Glaskugel im Moment nicht her.

04.09.2011 - 13:17 Uhr

Warum versuchst du nicht die Fehler zu beheben, anstatt sie nur auszublenden?

Weil sowohl das Managed Assembly als auch die aufgerufene Unmanaged-DLL nicht von uns, sondern von einem Projektpartner kommt und wir auch keine Sourcen davon haben... Wir greifen von außen nur über die Managed-DLL darauf zu.

Wir werden aber Montag mal Kontakt zu dem Partner aufnehmen.

04.09.2011 - 01:34 Uhr

Als Ergänzung:

Ich habe in demselben Programm zu beginn man eine anderen DLL mit falscher Calling Convention aufgerufen. Ob er an der stelle mit pInvokeStackImbalance abbricht, hängt in der Tat von dem Wert von NetFx40_PInvokeStackResilience ab.

Isofern scheint die andere pInvokeStackImbalance zwar bei .NET 3.5 ignoriert zu werden, nicht aber bei .NET 4.0 mit NetFx40_PInvokeStackResilience.

Bin langsam echt ratlos...

02.09.2011 - 22:41 Uhr

Habe jetzt die folgende Lösung:


class Base {
     public string Name { get; set; }
}

class Foo : Base { }
class Bar : Base { }

public ObservableCollection<Foo> Foos { get; private set; }
public ObservableCollection<Bar> Bars { get; private set; }
public IEnumerable<Base> References { get; private set; } //Wirft PropertyChangedEvent

Dann kann ich die Foos und Bars den References zuweisen (weil IEnumerable Kovariant ist), beim Binding wird das aber Anscheinend über Reflection aufgelöst, so dass auch bei References auf CollectionChanged-Events reagiert wird.

Dennoch bleibt die Typsicherheit bei Foo und Bar erhalten.

Selbst wenn Foo und Bar nicht von Base ableiten, könnte man References vom Type IEnumerable (nicht generisch) oder object definieren.

02.09.2011 - 15:07 Uhr

Ich portiere gerade eine Anwendung von WinForms auf WPF und gleichzeitig von .NET 3.5 auf .NET 4.0

Jetzt bekomme ich in einem Assembly, welches ich aber nicht ändern kann, ein pInvokeStackImbalance. Recherche ergab, dass dieses üblicherweise auf eine falsche Calling Convention zurückzuführen ist. Bis .NET 3.5 wurde sowas automatisch behoben, ab .NET 4.0 kommt ein Fehler.

Laut MSDN <NetFx40_PInvokeStackResilience> Element kann man durch

<NetFx40_PInvokeStackResilience enabled="1"/>

in der app.config das alte Verhalten erzwingen.

Bei mir funktioniert das aber nicht....

Hat jemand Ideen? Jetzt weiß ich nicht, ob das trotz dieser Info schief geht, oder ob er die garnicht erst erkennt / einliest.

Bin ziemlich ratlos und für jedne Tipp dankbar.

28.08.2011 - 21:16 Uhr

Ok, wenn ich dich richtig verstehe, verwende ich statt

 
public ObservableCollection<Foo> Foos { get; private set; }
public ObservableCollection<Bar> Bars { get; private set; }

dann


public ObservableCollection<Base> Foos { get; private set; }
public ObservableCollection<Base> Bars { get; private set; }

und kann diese dann dem Property Names zuweisen.

Eigentlich ziemlich offensichtliche Lösung (muss wohl auf dem Schlauch gestanden haben), allerdings zu dem Preis, dass ich in dem ViewModel typsicherheit verliere.

28.08.2011 - 20:28 Uhr

Also erstmal: Mit Optics geht es....


        public RefType RefType {
            get { return _refType; }
            set {
                if (RefType != value) {
                    _refType = value;
                    RaisePropertyChagend("RefType");
                    switch (_refType) {
                        case RefType.BarType:
                            Names = ExpressionObserver.Execute(this, t => t.Bars.Select(x => x.Name)).Cascade();
                            break;
                        case RefType.FooType:
                            Names = ExpressionObserver.Execute(this, t => t.Foos.Select(x => x.Name)).Cascade();
                            break;    
                    }
                }
            }
        }

Die Lösung mit der Polymorphie ist mir noch nicht klar...


    class Base {
        public string Name { get; set; }
         
    }

    class Foo : Base { }

    class Bar : Base { }

Aber was ist nun das Property Names? Ein ObservableCollection<Base>? Da kann ich dann zwar einzeln Foos oder Bars rein tun, aber doch niemals die ganze Liste zuweisen (ist leider nicht Kovariant). Wenn ich aber nur einzelne Werte hinzufüge, muss ich wieder händig auf das Hinzufügen neuer der Foos und Bars reagieren.

28.08.2011 - 20:03 Uhr

Hallo!

Folgendes Problem (ViewModel):


    class Foo {
        public string Name { get; set; }
    }

    class Bar {
        public string Name { get; set; }
    }

    public enum RefType {
        FooType,
        BarType
    };

    class ViewModel : INotifyPropertyChanged {
        RefType _refType;

        public ObservableCollection<Foo> Foos { get; private set; }
        public ObservableCollection<Bar> Bars { get; private set; }

        public RefType RefType {
            get { return _refType; }
            set {
                if (RefType != value) {
                    _refType = value;
                    RaisePropertyChagend("RefType");
                }
            }
        }

        //.......
    }

Jetzt binde ich eine ComboBox an die Foos, eine ComboBox an die Bars und eine an den RefType. Klappt alles.

Nun möchte ich noch eine weitere ComboBox, in der folgendes steht:
Wenn RefTypeFooType, soll die ComboBox die Namen aller Foos enthalten. Wenn RefTypeBarType, soll die ComboBox die Namen aller Bars enthalten.

Allerdings können sich die Collections Foos und Bars zur Laufzeit ändern. Wären diese statisch, würde ich im setter von RefType eine Collection setzen, und die ComboBox an diese binden:


        public RefType RefType {
            get { return _refType; }
            set {
                if (RefType != value) {
                    _refType = value;
                    RaisePropertyChagend("RefType");
                    switch (_refType) {
                        case RefType.BarType:
                            Names = Bars.Select(x => x.Name).ToArray(); break;
                        case RefType.FooType:
                            Names = Foos.Select(x => x.Name).ToArray();
                            break;    
                    }
                }
            }
        }

        IEnumerable<string> _names;
        public IEnumerable<string> Names {
            get { return _names; }
            private set {
                if (Names != value) {
                    _names = value;
                    RaisePropertyChagend("Names");
                }
            }
        }

Dann bekomme ich aber nicht mit, wenn ein neuer Foo bzw. Bar hinzugefügt wird.
Ich habe schon Optics entdeckt, was vermutlich das Problem lösen könnte (noch nicht probiert).

Gibt es eine im .NET-Framework enthaltene Lösung dafür?

Vielen Dank,
Uwe

16.08.2011 - 17:24 Uhr

Ich scheine noch zu sehr in Windows-Forms zu denken.

Dort habe ich immer verschiedene Controls bzw. UserControls gehabt, die nach außen hin eine möglichst schlanke Schnittstelle haben und ihre komplette Logik im inneren verbergen.

Ich wollte das nun in WPF ähnlich machen.

Wenn ich euch aber richtig verstehe, ist das der falsche Ansatz. Stattdessen sollte ich versuchen, relativ lose gekoppelte View Models mit schlanker Schnittstelle Zwischeneinander zu erzeugen. Dann Controls, welches ausschließlich mittels DataBinding zum DataContext an diese ViewModels gebunden werden? Diese können dann ggf. mittels Templates sogar automatisch erzeugt werden?

Übrigens Danke für den Hinweis mit dem Content Presenter. Den kannte ich bisher noch garnicht.

Wie gesagt: WPF- und MVVM-Anfänger...

16.08.2011 - 06:55 Uhr

Habe das nun mal durchgelesen und auch im Wesentlichen verstanden.

Allerdings ist IMHO meine Frage dort nicht beantwortet. Vielleicht kann ich sie nochmal konkretisieren:

Ich habe ein UserControl, welches aus anderen Controls zusammengesetzt ist. Die Schnittstelle nach außen ist schlank (ein Property), intern können komplexere Zustände angenommen werden.
Es gibt verschiedene solche Controls, die nach außen dieselbe Schnittstelle haben.

Ich möchte die gerne in der Art verwenden


<MyControl1 Solution="{Binding Solution}" />
<MyControl2 Solution="{Binding Solution}" />
<MyControl3 Solution="{Binding Solution}" />

Dafür müssen diese Controls ja ein DependencyProperty "Solution" haben.

Mir ist nicht klar, wo die (etwas) komplexere Logik der einzelnen Controls abläuft. In den CodeBehind-Dateien derselben? In einem eigenen ViewModel?

Ich vermute, es müsste ein eigenes ViewModel sein. Muss dieses ViewModel dann auch nach außen bekannt sein (fände ich unschön), oder wie kann ich das Property "Solution" (was ja ein DependencyProperty ist) so im Control implementieren, dass es nur an das (nur intern bekannte) ViewModel weitergereicht wird.

Vielen Dank,
Uwe

15.08.2011 - 19:54 Uhr

Naja - du musst ja nur die fertige Komponente nutzen und nichts nachimplementieren. Ist dir das wirklich zu einfach?

Nee, das ist schon OK. Ich habe nur immer ein blödes Gefühl, wenn ich eine mächtige Komponente einbinde um etwas zu lösen, von dem ich vermutet hätte (aber nicht weiß), ob das auch mit .NET Boardmitteln einfach geht.

Plakativ gesagt: Wenn ich an einer Stelle die Wahl habe zwischen 10 Zeilen und keiner Abhängigkeit oder hingegen 2 Zeilen und eine Assembly-Abhängigkeit, wähle ich lieber die 10 Zeilen.

Aber wenn es dergleichen wirklich nicht gibt, greife ich auf Bindable LINQ zurück...

15.08.2011 - 17:24 Uhr

Danke für den Link. Ich habe zwar ewig recherchiert und gelesen, den Artikel aber noch nicht. Melde mich dann morgen wieder, wenn ich ihn gelesen und (hoffentlich) verstanden habe 😉

15.08.2011 - 17:08 Uhr

Arbeite mich derzeit in WPF ein und habe da eine architektonische Frage...

Ich habe ein oder mehrere Control, welches eine Lösung (Solution) graphisch darstellen soll. Diese Controls können dumm sein (nur zeichnen) oder komplexere Interaktionen zulassen.

Unter WinForms haben diese Controls ein public Property vom Typ Solution gehabt und die gesamte internen Navigationsmöglichkeiten privat gehalten.

Angenommen ich entwickel nun ein solches Control als UserControl in WPF, zusammengesetzt aus verschiedenen anderen Controls, dann wäre für dieses Control eine eigenen MVVM-Architektur wünschenswert. Das gesamte ViewModel will ich aber außerhalb garnicht wissen, weil es eigentlich Internas des Controls sind. Nach außen muss ich nur ein Property "Solution" bereitstellen, welches ich binden kann.

Wie mache ich das nun? Es gibt es die Klassen
public View: UserControl
internal ViewModel: INotifyPropertyChanged

Damit ich das Solution-Property binden kann, muss es im View als Dependency Property bereitstehen. Aber eigentlich doch wieder nicht, weil das View dieses Property ja eigentlich nur an das ViewModel delegieren soll.

Vielen Dank,
Uwe

15.08.2011 - 16:57 Uhr

Sorry für meine lange Antwortzeit und danke für deine Antwort...

Das scheint mir recht mächtig zu sein, aber vermutlich auch overkill für meine Anforderung. Gibt es sonst wirklich keine Möglichkeit, eine Collection one-way zu einem Control zu binden und unterwegs noch elementare Transformationen durchzuführen?

09.08.2011 - 10:40 Uhr

Hallo!

Ich fange gerade an mit WPF und sehe vermutlich den Wald vor lauter Bäumen nicht. Habe auch schon gegooglet und das Data Binding Tutorial entdeckt, aber dennoch finde ich keine Einfache Lösung für mein Problem.


class Solution{
    public IEnumerable<string> Items; //Immutable
}

class SolutionManager{
    public ICollection<Solution> Solutions; //Kann auch ObservableCollection etc. werden

    public void AddSolutions(....)
    public void RemoveSolutions(....)
}

Nun möchte in eine ListBox an die LINQ-Expression binden:


solutionManager.Solutions.SelectMany(s=>s.Items).Distinct().OrderBy(s=>s)

Also alle verschiedenen Items aller Solutions im SolutionManager (idealerweise sortiert).

Natürlich kann ich eine eigene Klasse schreiben, die bei jeder Änderung des SolutionManagers den ausdruck berechnet und dann eine eigene ObservableCollection updatet, das scheint mir aber zu kompliziert.

Gibt es für sowas eine Elegante Lösung? Die im Tutorial beschriebenen CollectionViews?

Vielen Dank,
Uwe

21.06.2011 - 23:08 Uhr

Hallo!

Habs auch jetzt über ein Bitmap gemacht... Wobei mir nicht so richtig klar ist, wie das Problem zu Stande kommt. Vermutlich nutzt der ComboBoxRenderer irgendwelche Internen Eigenschaften des Graphics-Object, um direkt in den Grafikspeicher zu schreiben oder sowas.

Viele Grüße,
Uwe

21.06.2011 - 12:47 Uhr

Hallo!

Irgendwie ignoriert der ComboBoxRenderer die Graphics-Transformationen


    public class Form1 : Form {
        protected override void OnPaint(PaintEventArgs e) {
            e.Graphics.TranslateTransform(40, 40);
            e.Graphics.RotateTransform(30);
            Rectangle bounds = new Rectangle(40, 0, 80, 20);
            e.Graphics.FillRectangle(Brushes.Red, bounds);
            ComboBoxRenderer.DrawTextBox(e.Graphics, bounds, "Foo", Font, ComboBoxState.Normal);
            base.OnPaint(e);
        }
    }

Der Text ignoriert sowohl translate als auch rotate, die ComboBox ignoriert nur das rotate. Und warum der Hintergrund des mit FillRectangle gezeichneten Rechtecks weiß ist, weiß ich auch nicht....

Ich könnte alles erst in ein Bitmap zeichnen und das rotieren, ist aber auch unschön 😦

Hat jemand einen vorschlag, wie man eine um 90° nach links gedrehte ComboBox zeichnen kann?

Viele Grüße,
Uwe

06.06.2011 - 07:41 Uhr

Ich persönlich verwende das Strategy Pattern eigentlich ständig. Wobei man unter dem Begriff natürlich auch quasi alles verstehen kann....

Rein akademisch betrachtet ist selbst folgender Code irgendwie ein Strategy-Pattern....


listOfIntegers.first(x => x>=0);

04.06.2011 - 12:24 Uhr

Einige Tipps bzgl. Arbeit wurden ja gegeben: TODO-Liste, überfordert oder unterfordert dich das Projekt, hat es eine schlechte Code-Qualität (ist bei mir ein Motivationskiller).

Ansonsten würde ich aber auch versuchen, etwas relaxter auf der Arbeit zu sein. Häufig ist Stress oder Unausgeglichenheit ein Grund für sowas.

Ein Ansatz unabhängig von der Arbeit wäre: Aktive Freizeitgestaltung. Weg vom Rechner, was draußen machen, mit Freunden oder der Familie. Ich persönlich gehe gerne Wandern oder Geocachen.

Wenn ich abends oder am Wochenende am Rechner hänge, verdaddel ich meistens sinnlos Zeit im Internet. Verblüffend aber, dass auf SPON immer noch nix neues steht, ist doch ein Uhr nachts und das letzte mal habe ich vor 5 Minuten geschaut..... Wenns ganz schlimm kommt, schaue ich sogar bei MyCSharp 😁

Vielleicht hilft das schon. Bei mir reicht es manchmal. Wenn ich eine demotivierte Woche habe, laufe ich zur und von der Arbeit (5 km pro Richtung). Diese 90 Minuten Fußweg jeden Tag bieten mir Erholung.

Irgendjemand (finde das Zitat nicht mehr) hat mal gesagt "Ich kann mir nicht vorstellen, dass ich auf meinem Sterbebett liege und Sage: Ich wünschte, ich hätte mehr Zeit damit verbracht, auf meinem Hintern zu sitzen und auf Pixel zu starren".

22.05.2011 - 12:25 Uhr

Ein Kollege hat mich neulich gebeten, ihm bei einem Code zu helfen, den er von einem ausgeschiedenen Mitarbeiter übernommen hat.

Verteilt über eine etwas längliche Klasse mit wenigen hundert Zeilen (Zur anonymisierung des Projekts Namen etwas geändert, waren vorher aber auch nicht sprechender...):


public class SolverService
{
    private static readonly Random random = new Random(DateTime.Now.Millisecond);        
    delegate Item ApplyDelegate(List<Item> candidates);
    private const string ChoiceRandomName = "Random";
    private const string ChoiceFrequencyName = "Frequency";
    Dictionary<string, ApplyDelegate> choicesDelegates;
    
    public SolverService()
    {
        choicesDelegates = new Dictionary<string, NextCandidate>();
        MethodInfo mi = typeof(SolverService).GetMethod("ChoiceRandom", BindingFlags.NonPublic | BindingFlags.Static);
        ApplyDelegate applyDelegate = (ApplyDelegate)Delegate.CreateDelegate(typeof(ApplyDelegate), mi);
        choicesDelegates.Add(ChoiceRandomName, applyDelegate);

        mi = typeof(SolverService).GetMethod("ChoiceFrequency", BindingFlags.NonPublic | BindingFlags.Static);
        applyDelegate = (ApplyDelegate)Delegate.CreateDelegate(typeof(ApplyDelegate), mi);
        choicesDelegates.Add(ChoiceFrequencyName, applyDelegate);
    }

    public Item Perform(List<Item> candidates)
    {
        int next = random.Next(0, choicesDelegates.Count);
        string currentChoice = (next == 0) ? ChoiceRandomName : ChoiceFrequencyName;
        return choicesDelegates[currentChoice].Invoke(candidates);
    }

    private static Item ChoiceRandom(List<Item> candidates) { /*....*/ }
    private static Item ChoiceFrequency(List<Item> candidates) { /*....*/ }
}

Wir haben den Teil dann reduziert bekommen zu


public class SolverService {
    private static readonly Random random = new Random();

    public Item Perform(List<Item> candidates) {
        if (random.NextDouble() < 0.5) {
            return ChoiceRandom(candidates);
        } else {
            return ChoiceFrequency(candidates);
        }
    }

    private static Item ChoiceRandom(List<Item> candidates) { /*....*/ }
    private static Item ChoiceFrequency(List<Item> candidates) { /*....*/ }
}

Davon, dass nun eine IList im öffentlichen Interface schöner wäre, will ich garnicht erst anfangen...

03.05.2011 - 21:17 Uhr

Listen sind im Wesentlichen etwas komfortablere Wrapper um ein Array. Das einfachste wäre eine Liste von Kindern (in deinem Fall z.B. integers)

Du kannst das aber auch mit einem bool-Array machen. Das initialsierst du mit "true" für alle Kinder. Beim Abzählen inkrementierst du einen Zähler und musst die "false"-Werte überspringen.

Ich habe aber sehr stark den verdacht, das das gegen 1.1.1 Nicht nach Grundlagen fragen verstößt.

Lies dir mal eine Einführung in einem Buch durch, z.B. Visual C# 2010.

18.04.2011 - 11:28 Uhr

Ich brauche die Ableitung u.a. für das Newton-Raphson-Verfahren.

Da kenne ich mich leider nicht aus, ob es gute ableitungsfreie Alternativen gibt. Rekursive Bisektion ist ja im Mehrdimensionalen untauglich.

Der Fehler war nicht wirklich gross, bis auf 6 Nachkommastellen war der Wert richtig, aber wenn es schon andere Verfahren gibt, welche genauer sind ziehe ich diese vor.

Naja, das hängt halt davon ab, wie teuer Funktionsauswertungen sind. Beim Newton-Raphson-Verfahren brauchst du ja sowieso f(x_n). Wenn du nun Symmetrische Differenzen machst, dann benötigst du noch f(x_n - h) und f(x_n + h). Wenn du einseitige Differenzen machst, dann brauchst du nur noch f(x_n + h), weil ja f(x_n) schon berechnet ist.

Für Higher-Order-Methods brauchst du entsprechend noch mehr Funktionsauswertungen.

Ist halt ein Tradeoff: Genauere Differentiation führt zu weniger Iterationen, aber die Kosten einer Iteration steigt.

Der Fehler war nicht wirklich gross, bis auf 6 Nachkommastellen war der Wert richtig,

Das hängt natürlich vom Problem und der Größenordnung, in der die Funktionen leben, ab. Aber so für mich scheint ein solcher Fehler im Rahmen des Normalen zu liegen.

18.04.2011 - 10:15 Uhr

Um was für Funktionen geht es denn bei dir? Und wie groß war der Fehler?

Manchmal ist garnicht die numerische Ableitung das Problem, sondern die Funktionsauswertung (hatte das Problem schonmal bei einer schlichten quadratischen Form mit wenigen hunderttausend nicht-null-Einträgen).

Brauchst du denn wirklich die Steigung? Was willst du machen? Auch hier gibt es oftmals bessere Alternativen oder Verfahren, die ohne die Ableitung auskommen. In der Optimierung z.B. ableitungsfreie Verfahren oder, wenn nur die zweite Ableitung nicht berechnet werden kann, LBFGS anstelle von expliziten numerischen zweiten Ableitungen.

17.04.2011 - 19:23 Uhr

Hallo!

Math.Epsilon ist die kleinste positive Wert größer als 0. Der ist deutlich zu klein, um damit sinnvoll zu rechnen.

Man muss ein Wert h finden, der so groß ist, dass die Rundungsfehler keine Probleme bereiten, aber so klein, dass das mathematisch exakt genug ist.

Auf der Englischen Wikipedia Numerical differentiation steht dazu ein ganzer Abschnitt unter "Practical considerations using floating point arithmetic".

Im Wesentlichen wird dort h=sqrt(eps) * x vorgeschlagen (wobei ich das in h=sqrt(eps) * max(abs(x),1) abändern würde). Eps ist dabei das Maschinenepsilon und ungefähr 2.2e-16.

Wobei du dir überlegen solltest, symmetrische Differenzen oder Methoden höhrer Ordnung zu verwenden, das ist numerisch besser.

17.04.2011 - 11:39 Uhr

Geht ab .NET 4.0 (Schlüsselwörter in- und out bzw. zum Suchen Kovarianz und Kontravarianz)

Allerdings geht das eben nicht so einfach, sondern nur unter bestimmten Bedingungen.

Stell die Vor, Generic<Sub> wäre eine IList<Sub>. In der Methode Do(IList<Base> g) fügst du nun ein Element vom Typ Sub1, das ebenfalls von Base ableitet, hinzu. Dann hast du ein Sub1 in einer Liste von Subs.

Je nachdem, ob du was hinzufügst oder was aus der Collection rausholst, ist die Kompatibilität zwischen Generic<Base> und Generic<Sub> in unterschiedliche Richtungen.

13.04.2011 - 19:57 Uhr

Es ist jedoch bei den verschiedenen MVVM-Frameworks häufiger üblich die beiden Sachen zu trennen, schließlich soll ja das ViewModel die konkrete View nicht kennen,

Genau. Also gibt es drei Assemblies. ViewModel, ViewImpl und ViewIterface. Die Abhängigkeiten sind dann

ViewModel --> ViewInterface
ViewImpl --> ViewModel, ViewInterface

Und nirgends ist etwas zirkuläres.

11.04.2011 - 12:39 Uhr

Ich vermute, dass dem OP das klar ist. Ohne Reflection kommt man nur mit dem Namen eines Properties ja eh nicht an das Property dran. Insofern ist die Hauptfrage IMHO, wie man per Reflection eine Instanz einer Generischen Klasse erzeugen kann.

Die Frage die ich mir Stelle ist dabei, wie man die Collection dann weiterverarbeiten will. Weil ich sie ja niemals auf einen konkreten Typ Casten kann. Insofern wäre es evtl. sinnvoller, mit einer ObservableCollection<object> weiterzuarbeiten, wo eben die Werte des Properties drin stehen.

@Mini25
hast du denn wirklich nur den Namen des Properties? Wenn du das z.B. über eine lambda-expression auswerten könntest, wäre es einfacher. In Welchem Kontext brauchst du das denn?

08.04.2011 - 09:37 Uhr

Habe ich das richtig verstanden, dass damit die Schnittstelle IEnumerable eigentlich nur zum leichteren Handling von Arrays, Listen,... benutzt wird? Also z.B. die einfache Nutzung der foreach Anweisung etc.

Also ist dies eine "Erweiterung" zu Listen?

Jein. Bei der STL in C++ werden die ganzen Konzepte zur Compilezeit mittels Templates umgesetzt. Ein std::sort ist templatisiert.

Bei C# ist das ganze über Polymorphie gelöst. Wenn du nun also eine Methode schreibst, die z.B. das Maximum aus einer Sammlung von Integern suchen willst, dann gibst du der Methode als Parameter ein IEnumerable<int>. Dadurch kannst du die Methode dann für List, LinkedList, Array, ... anwenden. Eben alles, was IEnumerable implementiert.

Lies die dazu aber am besten mal das Konzept von Interfaces durch. Das ist in Java und C# noch wichtiger als in C++.

30.03.2011 - 12:04 Uhr

Bei den von Dir genannten Datenmengen ist Lazyloading und der damit verbundene Aufwand sicherlich zu teuer.
Lazy Loading benutzt man, um Lade und Verarbeitungszeiten zu verkürzen.

Ich versuche mal ein Beispiel zu bringen, wo ich an einen Einsatz dachte. Ist fiktiv, beschreibt aber mein Problem.

Angenommen, es gibt ein Objekt "Abteilung", welches als Property eine Liste von Mitarbeiten hat. Evtl. Hat es aber auch noch eine Liste von Projekten etc.

Würde nun, wenn ich die Abteilung aus der Datenbank lade, die gesamten Mitarbeiter, Projekte etc. alle direkt mit geladen? Oder würden diese erst dann geladen, wenn ich wirklich die Mitarbeiter der Abteilung brauche.

Oder würde man das bei einem Datenbank-Layer planarer halten? So dass die Abteilungen gar keine Property "Mitarbeiter" hat und stattdessen fragt man die Datenbankschicht in einer Methode "Gib mir mal die Mitarbeiter von Abteilung XY".

Vermutlich ist es wieder ein "kommt drauf an..."

Als erstes müsst ihr euch irgendwann entscheiden welche Technik ihr einsetzen wollt, denn NHibernate und EF

Bei uns ist, gefühlt durch Münzwurf, die Entscheidung erstmal auf NHibernate gefallen. Wirkte so, als ob man damit am wenigsten falsch machen kann. Fundiert war sie aber nicht.

Als Datenbanken kommen bei uns PostgreSQL, MSSQL und (nicht lachen...) Access vor. Das erstelen des Schemas ist gefühlt eigentlich kein größeres Problem.

Und was ganz wichtig ist, versuche nicht es gleich von Anfang an Perfekt zu machen, denn erstens gibt es kein Perfekt, und zweitens wirst du auf dem Weg verzweifeln.
Bedenke die "normalen" Vorgehensweisen, benutze Pattern mit Augenmaß und mache dich darauf gefasst, das du gefühlte 100 mal neu anfängst.

Danke für die Aufmunterung. Ich fürchte, dass es dann auf sowas hinausläuft. Von dem Moment, wo man seine erste Klasse erstellt hat bis zu dem Moment, wo man vernünftige Softwarestrukturen erstellt, dauert es ja auch ein wenig...

Habe gerade noch als (mir ganz gut erscheinendes) Tutorial gefunden http://msdn.microsoft.com/en-us/magazine/dd569757.aspx

30.03.2011 - 09:08 Uhr

Ich halte bei uns Performance für nahezu unkritisch. Dazu sind unsere Datenmengen zu klein.

Transaktionssicherheit ist in maßen kritisch. Die Datenbank sollte also im Normalbetrieb sicher funktionieren, wenn aber nun an der dümmstmöglichen Stelle der Strom ausfällt, darf auch mal was kaputt gehen.

Ich halte es auch für unwahrscheinlich, dass das Datenbank-System ausgetauscht wird.

Bei uns ist eher die Anwendung volatil. Meistens geht es eben (forschungsumfeld) um neuartige Dinge / Workflow, da wünscht man sich auch schon mal was, und wenn man es nach zwei Monaten sieht stellt man fest, dass es einem in der Praxis nichts nützt. Manchmal ist es sogar nur Prototypenentwicklung oder ein Proof of Concept.

Es kommen also recht oft neue Feautures hinzu oder alte werden entsorgt. Insofern sollte die Datenbankschicht möglichst sauber, einfach verwendbar, erweiterbar und/oder modifizierbar sein.

Sauberkeit und Flexibilität hat oberste Priorität, Performance und Sicherheit sind zweitrangig.

Achso: Es geht üblicherweise um Desktop-Anwendungen (WinForms, oftmals auch lokale DB).

29.03.2011 - 18:52 Uhr

Hallo!

Die Frage ist sehr allgemein und wurde mit Sicherheit schon mal beantwortet. Ich verliere mich aber etwas im Dschungel der Begriffe.

Ich entwickle beruflich Software, angewandte mathematische Forschung, oft auch als Dienstleistung für Firmen. Meistens mehr oder weniger komplizierte Algorithmen mit einer mehr oder weniger komplexen GUI zur Interaktion und Visualisierung der Lösungen. Umfang i.d.R. mehrere Mannmonate bis wenige Mannjahre.

Bisher hatten wir recht wenige mit Datenbanken zu tun. Daten waren i.d.R. Datei einlesen -> Komplexe Rechnungen mit GUI-Interaktion -> Daten Schreiben. Das dann entweder in Datenbanken, Textdateien oder XML.

In letzter Zeit kommen aber vermehrt Projekte, in denen wir mit für uns komplizierteren Datenabläufen zu tun haben. Also Modifikation der Daten in der Datenbank, auf Grund der Datenmenge können nicht alle Daten in den Speicher gelesen werden etc.

Im Prinzip wird also eine saubere Datenbankschicht notwendig. Vernünftige Datenbanken in Normalform zu erstellen ist bei unserer Komplexität kein wirkliches Problem.

Jetzt haben wir angefangen uns mit OR-Mappern wie NHibernate zu beschäftigen. Alternativ kenne ich auch noch das Entity Framework. Die Technik ist auch irgendwie klar, aber trotzdem scheine ich das ganze Konzept nicht richtig zu verstehen. Ich fühle mich wie ein Umsteiger von Prozeduraler zu Objektorientierter Programmierung, der nun nicht weiß, was er mit seinen ganzen Klassen machen soll.

Fragen die eben auftauchen:

  1. Wie kann man Lazy Loading einfach in der Datenbankschicht implementieren (wenn es denn das richtige Konzept für unser Problem ist...)
  2. Wie kann man sicherstellen, dass es für in der Datenbank gespeicherten Entitäten immer nur ein Objekt gibt, also dass es keine verschiedenen Objekte für dasselbe "Ding" in der Datenbank gibt.
  3. Ist diese referenzielle Gleichheit in 2. überhaupt sinnvoll und notwendig?
  4. Diese Liste es beliebig erweiterbar, also: Wie schreibe ich eine gute Datenbankschicht für ein kleines bis mittelgroßes Projekt.

Kennt jemand gute Tipps, Tutorials oder Bücher, um einen Einstieg in das Thema zu ermöglichen? Oder Begrifflichkeiten, nach denen man noch irgendwie googlen kann?

Viele Grüße,
Uwe

22.03.2011 - 18:09 Uhr

Willst du es denn für allgemeine Klassen haben?
Was spricht dagegen, das der Erzeuger sich selbst an das zu erstellende Objekt übergibt. Evtl. als Interface, um keine Kreisbeziehung zu haben?