Laden...
Avatar #avatar-4122.png
LaTino myCSharp.de - Experte
Softwareentwickler Thüringen Dabei seit 03.04.2006 3.003 Beiträge
Benutzerbeschreibung

Forenbeiträge von LaTino Ingesamt 3.003 Beiträge

30.06.2017 - 11:50 Uhr

Gib deinem VM eine Eigenschaft, die die Liste der uints aggregiert, anstatt die Aggregierung im View zu versuchen.

LaTino

26.06.2017 - 13:07 Uhr

@LaTino
Meines wissens wird das UnknownElement nur bei der deserialisierung aufgerufen.

Stimmt, dann hat sich das auch erledigt. Ich scheitere auch etwas dran, mir auszumalen, wofür das gut sein könnte. Wenn ich so einen Knoten mit variablem Namen in mein XML schreibe, wie zum Teufel soll ich dann beim Deserialisieren rausfinden, in welche Klasse ich deserialisiere?

LaTino

26.06.2017 - 08:54 Uhr

Nein, nicht mit dem XmlSerializer. Nicht ohne weiteres, siehe unten.

XmlSerializer und die XmlElementAttribute-Klasse arbeiten so zusammen, dass verschiedene Instanzen einer Klasse nach der Serialisierung ein und demselben XML-Schema entsprechen. Das heisst, die Tatsache, dass die XML-Knoten immer gleich heißen, ist absolut erwünscht.

Was meine ich mit "nicht ohne weiteres"? Naja, einen kleinen, etwas unsauberen Kniff gibt es.
Lass das XmlElementAttribute weg und abonnier das UnknownElement-Ereignis des von dir verwendeten XmlSerializers. Dann kannst du die Serialisierung/Deserialisierung noch beeinflussen.

Besser wäre ein eigener Serializer für solche Fälle. Das klingt auch nur nach großem Aufwand, so schlimm ist das nicht. (EDIT: das Stück Code eben ist ja an sich schon der (naive) Ansatz für einen Serializer)

LaTino

26.06.2017 - 07:48 Uhr

Da du von XElement redest, gehe ich mal von Linq to XML aus.

(Vorab: ThomasE.s Hinweis mit dem XmlSerializer ist - meistens - die bessere Variante.)

Natürlich kann man die Name-Eigenschaft einer XElement-Instanz zur Laufzeit (= dynamisch) ändern.


class ExampleClass
{
    public bool ExampleProperty { get; set; }

    public void SaveAsXml(string path)
    {
        new XDocument(
            new XDeclaration("1.0", "UTF-8", "true"), 
            new XElement(GetType().Name, 
                new XAttribute("referenceId", GetHashCode()),
                new XElement(nameof(ExampleProperty), ExampleProperty)
            )
        )
        .Save(path);
    }
}

Wobei ich irgendwie vermute, dass das nicht deine Frage war, aber mangels Glaskugel...

LaTino

23.06.2017 - 08:11 Uhr

Wurde ja schon gesagt, dass die Zeichenketten Ursache des Speicherproblems sind, das du hast. Dann serialisierst/deserialisierst du halt in einen (File-)Stream.


//there....

MyClass sourceObject = GetLargeObject();

JsonSerializer serializer = new JsonSerializer();
//Converter je nach Gusto hinzufügen, serializer konfigurieren....

using (var sw = new StreamWriter(filePath))
using (var writer = new JsonTextWriter(sw))
    serializer.Serialize(writer, sourceObject);


//...and back again.

MyClass destinationObject;

using (StreamReader file = File.OpenText(filePath))
{
    JsonSerializer serializer = new JsonSerializer();
    destinationObject = (MyClass)serializer.Deserialize(file, typeof(MyClass));
}

LaTino

EDIT: geht auch mit einem MemoryStream, und ich würde fast behaupten, auch da kannst wesentlich größere Objekte behandeln als auf deine bisherige Weise. Muss also kein File sein.

21.06.2017 - 14:46 Uhr

Weil du die Variable db_config vom Typ DBConfig in der Main-Methode der Klasse deklarierst, ist sie auch nur innerhalb der Main-Methode verfügbar. Möglicherweise suchst du das hier: Felder, um die Variable über den Gültigkeitsbereich der Main()-Methode hinaus parat zu haben. Das wäre allerdings schon die Grundlage der Grundlagen und ein Anlass, sich erst einmal ein Buch zu schnappen und durch zu arbeiten.

Bitte auch [Artikel] C#: Richtlinien für die Namensvergabe beachten.

LaTino

21.06.2017 - 09:44 Uhr

Die Webseite caffe.de benutzt - sagt mir jedenfalls mein Chrome - TLS 1.2. Versuch mal, die SecurityProtocol-Property entsprechend einzuschränken, also ausschließlich SecruityProtocolType.Tls12 festzulegen.

LaTino

01.06.2017 - 07:34 Uhr

Ob SQLite-net-PCL das Query printet, werde ich mir gleich mal ansehen. Ist mir aber bisher nicht aufgefallen. Muss dafür irgendwas gesetzt werden?

Möglich, kann ich dir aus dem Hut nicht sagen. Sollte aber gut googlebar sein 😉. (Ich hab das mal bei einem Kollegen gesehen, der genau wie du wissen wollte, wie gut die per Linq erzeugten Abfragen sind.

LaTino

01.06.2017 - 07:27 Uhr

Wir haben ca. alle vier Wochen ein Release. Zwischen den Abzügen des release-branches liegen je so etwa 4-5000 commits im trunk, die jeweils mit einem Task/Ticket verknüpft sein müssen. Anders als von Abt beschrieben (hier im Haus allerdings mit svn anstelle von Git) geht das m.E. gar nicht, wenn man niemanden einstellen will, der ausschließlich release notes erstellt.

LaTino

31.05.2017 - 16:29 Uhr

Schreibt net-PCL nicht das generierte SQL in die Debug-Ausgabe?

Müsste eigentlich. Wenn ja, kannst du ja vergleichen.

LaTino

30.05.2017 - 15:32 Uhr

@sth_wired, so etwa:


interface IMessage { }

class GenericMessage<T> : IMessage
{
    public T DataItem { get; set; }
}

static class IMessageExtensions
{
    public static object GetDataItem(this IMessage message) => message.GetType().GetProperty("DataItem")?.GetValue(message);
}

void GetDataItemTest()
{
    var myList = new List<IMessage>
    {
        new GenericMessage<int> { DataItem = 5},
        new GenericMessage<string> { DataItem = "hello, world"},
        new GenericMessage<ConsoleColor> { DataItem = ConsoleColor.Black }
    };

    myList.Select(p => p.GetDataItem().ToString()).ToList().ForEach(Console.WriteLine);
}

@Paladin: reicht Zugriff auf Implementierung, s.o....ist egal, hat sie ja beides nicht 😉.

LaTino

30.05.2017 - 14:29 Uhr

@LaTino:
Streng genommen ist ein GenericMessage<T> ein normaler Typ, zumindest behandelt .NET das als normalen Typ. An den kommst Du mit typeof(GenericMessage<>)

Das meinte ich nicht. Wären die Implementierungen von IMessage in der erhaltenen IEnumerable<IMessage> nicht generisch, dann könnte man bequem auf jede in der Liste enthaltene Instanz zugreifen, wenn man ihren Typ kennt.

Bei einer Implementierung von IMessage als generischer Typ geht das nicht, selbst wenn man weiß, welche Implementierung (hier: GenericMessage<>) benutzt wird: man muss schon den konkreten constructed type kennen. Das war mein Punkt. Generische Argumente kann man ausschließlich per Reflection oder per Selbstauskunft (zB über ein Property DataItem, das in einer Basisklasse oder dem Interface deklariert wird) erschließen.

Auf den generischen Typ kannst du eben nur casten, wenn du das generische Argument (und damit den constructed type) kennst. Ansonsten bleibt dir nur Reflection.

LaTino

30.05.2017 - 12:34 Uhr

Wenn es nicht per Reflection sein soll, müsstest du einen Basistypen einziehen, der DataItem abstrakt implementiert und von dem GenericMessage<T> erbt.

Der Irrtum bzw das Problem ist, anzunehmen, dass GenericMessage<T> ein Typ sei. Ist es nicht, deshalb kann man auch nicht auf GenericMessage<T> casten (sondern eben auf GenericMessage<int> usw., denn das sind Typen).

Wenn du die Möglichkeit einer abstrakten Basisklasse nicht hast - und es klingt so - solltest du es per Reflection in einer Extension lösen. (Auf propertyinfo "DataItem" testen und Wert extrahieren.)

LaTino

29.05.2017 - 07:36 Uhr

JSON Serializer wandelt meine DB Datumsfelder
JSON arbeitet eigentlich mit ISO 8601 und nicht mit Date(<Unix Timestamp>)
Was für ein Serializer soll das denn sein?

So einen Mist baut m.W. nur DataContractJsonSerializer. Was mich wundert, weil hier nirgends von einem WCF-Service die Rede war.

LaTino

26.05.2017 - 19:56 Uhr

Nochmal: nicht der GC ist schuld an schlechter Performance, der Entwickler ist es. Das scheint irgendwie nicht bei dir anzukommen. Das Konzept der Garbage collection ist nicht per se unperformant. Unreal engine, Unity 3D, cry engine (in Teilen)...benutzen alle garbage collection. "Wenn's an der Performance hapert, benutz ich halt unsafe"...oje.

LaTino

24.05.2017 - 13:13 Uhr

Ich habe nicht den Editor als Frickelei bezeichnet, sondern das Einrichten einer vernünftigen Arbeitsumgebung damit: passende Extensions raussuchen, vergleichen, installieren, einrichten. Das ist zusätzlicher Aufwand ggü einer Entwicklung in VS. Bitte nix unterstellen, was ich nicht gesagt habe 😃

LaTino

24.05.2017 - 10:41 Uhr

Gut gemeinter Rat: vermeidet die unnötigen Dependencies auf die Microsoft Packages und orientiert euch direkt an Angular.

Ich bezweifle gar nicht, dass das Arbeiten mit VSC an der Stelle viel glatter vonstatten gehen kann. Allerdings verlangt das eine Umstellung & Umgewöhnung der kompletten Arbeitsumgebung. Ich hab selber immer noch Schwierigkeiten, mich mit VSC als Editor anzufreunden. Die Frickelei mit Extensions hier installieren, da konfigurieren, wissen, welche man braucht etc pp - liegt mir nicht, interessiert mich eigentlich auch nicht, ich will einfach nur arbeiten. Wenn ich dann eine Möglichkeit finde - und sei es mit zusätzlichen Paketen - in meiner gewohnten Umgebung arbeiten zu können, dann tu ich das. Spart Zeit und Nerven - auch, wenn es aus Sicht derjenigen, die eben ein anderes Arbeiten gewohnt sind, wieder umständlich ist.

LaTino

24.05.2017 - 09:50 Uhr

Projekttyp im VS wäre dann eine ASP.NET Core Webanwendung und Clientseitig lädst du dir alle Abhängigkeiten mit Node bzw dem Node Package Manager (npm). Du kannst dir auch einen kleinen Webserver installieren (node serve, lite-server, webpack-dev-server, ...) mit dem du dann clientseitig entwickeln kannst. Das einzige, was dein Client vom Server kennt ist dann die URL.

Oder:


Kommandozeile, Templates installieren:
dotnet new --install Microsoft.AspNetCore.SpaTemplates::*

Kommandozeile, Verzeichnis anlegen...
mkdir MyNewAngularProject
cd MyNewAngularProject

Kommandozeile, Angular-Projekt erzeugen
dotnet new Angular

Erzeugte Projektmappe dann im VS2017 öffnen und warten, bis er die Abhängigkeiten aktualisiert hat. Dann kannst du wie gewohnt im VS loslegen.

LaTino
EDIT: Quelle und mMn mit großem Abstand bestes verfügbares Angular-mit-asp.net-core-Tutorial:
https://jonhilton.net/2017/02/21/create-a-vs2017-angular-2-and-net-core-site-using-the-command-line/

24.05.2017 - 07:42 Uhr

Das angehängt Dokument ist zwar kein gültiges XML (da sind ein paar Knoten, die geschlossen, aber nicht geöffnet werden - vermutlich beim editieren passiert), aber es wird klarer, was du tun möchtest:

Aus allen Knoten "Dokument" den Inhalt des Unterknotens "Binardaten" in eine Datei mit dem Namen des Attributs "Dateiname" des Dokument-Knotens schreiben. Im Binardaten-Knoten stehen die Daten als byte-Array, base64-encoded. Richtig?

Du musst das ganze nicht auf Händen und Knien (XmlReader) machen. Mit Linq to XML sieht das so aus:


const string BASE_PATH = @"c:\temp";
const string XML_PATH = @"c:\pfad\zu\XML-Muster.xml";
const string FILENAME_ATTR = "Dateiname";
const string ELEMENT_BIN = "Binardaten";
const string ELEMENT_NAME = "Dokument";

XDocument.Load(XML_PATH).Root.Descendants(ELEMENT_NAME)
    .Where(p => p.Attribute(FILENAME_ATTR) != null && p.Element(ELEMENT_BIN) != null)
    .ToList()
    .ForEach(p => File.WriteAllBytes(Path.Combine(BASE_PATH, p.Attribute(FILENAME_ATTR).Value),
                    Convert.FromBase64String(p.Element(ELEMENT_BIN).Value)));

Also eine Zeile 😉.

LaTino
EDIT: strings als Konstanten zwecks Übersicht/Anpassbarkeit

23.05.2017 - 16:34 Uhr

Garbage Collection ist eben nicht trivial. Wenn man in den Bereich kommt, wo man den GC tunen muss, wird es haarig. Dafür merkt man dann aber auch den Unterschied zwischen Entwicklern und Fricklern. Minecraft als Beleg für schlechte Java-Performance heranzuziehen ist genau so fair,, als würde ich BER als Beleg dafür nehmen, dass Deutschland die guten Ingenieure ausgehen. Beides Quatsch.

http://www.mono-project.com/docs/advanced/garbage-collector/sgen/

LaTino

23.05.2017 - 15:13 Uhr

Darf man fragen, wo du das her hast? Ich halte das für eine ziemlich abenteuerliche Behauptung.

LaTino

23.05.2017 - 14:06 Uhr

Die Performanceprobleme von Minecraft direkt auf Java zu schieben, halte ich für ziemlich naiv. Die gewählte Programmiersprache ist der letzte Schuldige.

LaTino

19.05.2017 - 15:26 Uhr

Oft muss man mit Attributen noch etwas Feinjustage betreiben (z.B. bei solchen Eigenschaftsnamen wie @code) und dann sieht man vor lauter Xml-, Json-, ... Serialisierungs-Attributen die eigentliche Klasse nicht mehr (wenn man eine Klasse für alle Formate definiert).

...oder man hat Eigenschaften, die sich gar nicht mit (Standard-)Attributen abbilden lassen (Namespace-Versionierung zB, man stelle sich für 10 verschiedene Versionen eines XML-Schemas vor, dass man jedesmal dasselbe Objekt wieder neu anlegen muss...gruselig). Der Punkt ist: es gibt Serialisierungs- und Deserialisierungsframeworks, und die können das vollständiger und vermutlich auch noch schneller, als wenn man das Problem von Hand löst. @TE: Daher, wie gesagt, arbeite mit fertigen Klassen.

LaTino

19.05.2017 - 15:14 Uhr

Ich war der Meinung, das der weg kann, weil die Sourcen eh im git liegen und Code der auskommentiert ist so gut wie immer weg kann.

This. Kenne aber auch so ein paar Messies, die am liebsten nie was löschen würden, sondern nur auskommentieren (und natürlich noch Kommentare dazu, WARUM etwas auskommentiert wurde).

LaTino

19.05.2017 - 14:18 Uhr

und für mich wie eine Demonstration von NIH anhand von Lazy<T>.

Yep, war tatsächlich eine Motivation. Allerdings kein NIH - benötigt für net 2.0/CF.

LaTino

19.05.2017 - 14:13 Uhr

also wäre jetzt der richtige Weg eine Klasse zu definieren und dann in die Klasse zu deserialisieren ? Dann gibt es ja auch wieder den Weg das als XML zu machen (der Anbieter bietet beide Varianten an). Ohne jetzt eine Grundsatzdiskussion anzufangen, findet Ihr JSON oder XML besser ? Spontan fällt mir da die geringere Datenmenge bei JSON ein.

Wenn du eine Klasse hast, in die du deserialierst, ist dir im besten Fall egal, woraus du es deserialisierst (ob json oder xml). Die Jungs, die dir deine Daten hier liefern, bieten ja auch beides an, und ich möchte doch sehr bezweifeln, dass sie das xml/json von Hand zusammenbauen 😉. Diese beiden Formate stehen nicht in Konkurrenz, sie ergänzen einander. Genausogut könntest du fragen, ob man einen Kreuzschlitz- oder einen Schlitzschraubenzieher besser findet.

LaTino

19.05.2017 - 10:06 Uhr

Etwas sauberer mit CopyTo/CopyToAsync.

EDIT: my bad. Framework 3.5.

LaTino

19.05.2017 - 09:42 Uhr

Hm, jein. Das gewünschte Verhalten an sich ist nix schlimmes, die Verwendung birgt in sich aber ein hohes Risiko, Probleme zu bereiten. (siehe Setteraufruf im Konstruktor, was eben wirklich in die Hose gehen kann und nicht offensichtlich ist). Tatsächlich sind hier die Tests für die betreffenden Komponenten unter denen, die am häufigsten rot werden. Nur ist der Einsatz gerechtfertigt und auch nicht ohne weiteres ersetzbar 😃. Wenn man's braucht, sollte man zusehen, ob man sein Design nicht so ändern kann, dass Variante eins - simples readonly - benutzt werden kann. Dann ist man auf der sicheren Seite, und bekommt obendrein sogar Compilerfehler, wenn man's falsch macht.

LaTino

19.05.2017 - 07:23 Uhr

Wie gesagt, wenn man etwas intensiver mit property injection arbeitet, kann das unter Umständen ganz hilfreich sein. Natürlich kann man property injection komplett mit c'tor injection abbilden, aber es ist nunmal situationsabhängig, welche Methode ich einsetze.

Bin etwas befremdet darüber, dass bestimmte Techniken abgelehnt werden, nur weil einem kein Beispiel einfällt, wofür man selbst das brauchen könnte. Wenn man xy erreichen will, hat man Möglichkeit a, b und c, das zu erreichen. Da muss ich doch nicht darübner diskutieren, dass man selbst noch nie xy erreichen wollte.

LaTino

EDIT:
Noch mal langsam:

  • sinnvoll, um einen Wert einmalig mit etwas zu füllen, dass zur Konstruktion noch nicht verfügbar ist. Nennt es write-once lazy loading, jedenfalls mit einer Mechanik, die sicherstellt, dass nur einmal gesetzt wird. Dass das hilfreich ist, wenn -zig Leute am Code rumbauen, von denen nicht jeder weiß, dass die Prop gesetzt sein muss, und dass sie nur einmal gesetzt werden sollte, muss ich nicht wirklich erläutern?
  • im Konstruktor einen Setter aufrufen? Soviel Masochismus habe ich dann doch nicht, danke 😄.
  • Ja, ich gestehe gern zu, dass das Sonderfälle sind. Es kann aber hilfreich sein, und wenn man es braucht, hat man die obigen drei Möglichkeiten, es einigermaßen sauber zu implementieren.
18.05.2017 - 15:36 Uhr

Vorsicht, antipattern: stringly typed programming. Alles in formlose Container packen und Key-Informationen als Zeichenketten speichern...bäks, wir sind doch nicht in VB6.

LaTino

18.05.2017 - 15:30 Uhr

Für readonly?

Die anderen Möglichkeiten sind ausschließlich dafür gedacht, die Beschränkung von readonly (Setzen ausschließlich im c'tor oder Deklaration) zu umgehen. So was ähnliches ist bei uns zB in den Factories im Einsatz, um die Stellen handlicher zu machen, die IoC per Property Injection realisieren. Oder du setzt eine readonly-Variable, die Werte benötigt, die im Konstruktor noch nicht verfügbar sind.

Letzten Endes alles Fälle, um die Art und Weise, wie eine Property benutzt wird, weiter einzuschränken, als die Sprache selbst das erlauben würde.

LaTino

18.05.2017 - 08:27 Uhr

Stimmt. Eine Möglichkeit, das zu tun, habe ich mal ergänzt.

LaTino

18.05.2017 - 08:07 Uhr

Die .exe aus dem Debug-Ordner einfach rauszukopieren...dafür sollte man dir auch schon die Ohren lang ziehen!

Wenn du dir mal dein "Erstellen"-Menü genauer anschaust, wirst du dort einen Punkt "Veröffentlichen" finden. Da ist dein Startpunkt. (EDIT: eng. => Build-Publish)

Oder hier:

.NET Core Application Deployment

LaTino

18.05.2017 - 07:58 Uhr

(@mods: falls das doch in die snippets soll, nur zu, ich war mir unsicher)


Das Schlüsselwort [tt]readonly[/tt] kann auf Felder einer Klasse angewendet werden. Felder, die so markiert werden, können für nicht-statische Klassen nur direkt bei der Deklaration, oder im Konstruktor der Klasse gesetzt werden. Danach können sie nicht mehr verändert werden.
[csharp]
class ExampleClass
{
    private readonly int _readonlyField;

    public int ReadonlyProperty => _readonlyField;

    public ExampleClass(int readonlyValue)
    {
        _readonlyField = readonlyValue; //einziges Mal, dass die Variable gesetzt werden kann.
    }
}
[/csharp]


Diese Möglichkeit eignet sich für Werttypen - Zahlen zum Beispiel. Das Feld, in dem ihr Wert gespeichert wird, ist ein Nullable<T>, und der Setter des Property prüft, ob das Feld bereits einen Wert hat.

[csharp]
class ExampleClass
{
    private int? _nullableField;

    public int? ReadonlyProperty
    {
        get
        {
            if(_nullableField.HasValue) return _nullableField;
            throw new InvalidOperationException($"Field {nameof(_nullableField)} has not been set (yet)!");
        }
        set
        {
            if(_nullableField.HasValue) throw new InvalidOperationException($"Field {nameof(_nullableField)} has already been set!");
            _nullableField = value;
        }
    }
}
[/csharp]


Ein Set-Memory ist einfach eine Variable, in der gespeichert wird, ob eine Property gesetzt wurde oder nicht. Diese Möglichkeit eignet sich für alle Typen, funktioniert aber nur, wenn der Set-Memory auch wirklich jedesmal gesetzt wird, wenn die Property sich ändert.
[csharp]
class ExampleClass
{
    private bool _setMemory;
    private int _readonlyProperty;

    public int ReadonlyProperty
    {
        get { return _readonlyProperty; }
        set
        {
            if (!_setMemory)
            {
                _readonlyProperty = value;
                _setMemory = true;
            }
            else throw new InvalidOperationException($"Field {nameof(_readonlyProperty)} has already been set!");
        }
    }
}
[/csharp]


Die in Möglichkeit drei beschriebene Vorgehensweise lässt sich natürlich noch in eine eigene Klasse kapseln, so dass die Übersicht in der benutzenden Klasse nicht verloren geht.

(Vorschlag T-Virus)
[csharp]
class ExampleClass
{
    private readonly SetAnywhereReadonly<int> _readonlyValue = new SetAnywhereReadonly<int>();

    public int ReadonlyProperty
    {
        get => _readonlyValue.Value;
        set => _readonlyValue.Value = value;
    }
}

class SetAnywhereReadonly<T>
{
    private bool _setMemory;
    private T _value;

    public T Value
    {
        get => _value;
        set
        {
            if (!_setMemory)
            {
                _value = value;
                _setMemory = true;
            }
            else throw new InvalidOperationException($"Field {nameof(_value)} has already been set!");
        }
    }
}
[/csharp]

LaTino
(ruhig ergänzen / diskutieren)
EDIT: Vorschlag von T-Virus ergänzt

18.05.2017 - 07:39 Uhr

@LaTino

Kannst du mir einmal genau erklären was :

  
  
BagObject[] bagObjectList = Enumerable.Range(0, objectCount).Select(p => new BagObject.....  
  
  

Ich kann damit ehrlich gesagt nicht so viel mit anfangen.

Deshalb habe ich darunter noch eine andere Schreibweise aufgeschrieben, die dasselbe macht. Wörtlich übersetzt macht der Code das hier:

  • für eine Menge von Zahlen (und zwar <objectCount> viele) (Enumerable.Range(0, objectCount)
  • erstelle pro Zahl eine Instanz der Klasse BagObject (Select p => new BagObject())
    (- sortiere nach der Eigenschaft "Efficiency") OrderBy(p => p.Efficiency)
  • und liefere die Ergebnismenge als Array (ToArray())

Alles zusammen:


BagObject[] orderedBagObjectList = Enumerable.Range(0, objectCount).Select(p => new BagObject
{
    Name = GetRandomName,
    Mass = GetRandomNumber(),
    Price = GetRandomPrice()
}.OrderBy(p => p.Efficiency).ToArray();

Ist nur eine Art, Dinge aufzuschreiben. Eine for-schleife wäre eine andere Art, diese hier nennt man Linq.

Davon abgesehen ist die Efficiency-Eigenschaft, nach der du sortieren möchtest, kaputt. Abt hat schon angedeutet, was da verkehrt ist. Ich glaube aber, der Sinn dahinter war, dass du eine Read-Only-Eigenschaft haben möchtest, die nur ein einziges Mal gesetzt wird und dann nie wieder verändert werden soll. Und ob sie gesetzt ist, erkennst du daran, dass sie nicht 0 ist.

Das ist
a) ein ganz furchtbarer Ansatz, weil eine Efficiency von 0 durchaus Sinn ergeben würde, deine Klasse das aber nicht abbilden kann und
b) das Rad neu (und schlechter) erfunden, denn so eine Mechanik existiert bereits. Eigentlich existieren sogar mehrere Möglichkeiten. Aber das sollte Thema eines anderen Threads sein.

LaTino
EDIT: Thread ergänzt

17.05.2017 - 15:15 Uhr

Mal ne doofe Frage:

Wo seht ihr hier einen IComparer? Ich sehe nur etwas, was man einem Comparison<T> zuweisen könnte. 😉

Ich hatte ihn so verstanden, dass er einen IComparer schreiben wollte, aber irgendwie durcheinandergekommen und beim Comparison<T>-Delegaten hängengeblieben ist. So richtig gibt das sein Posting aber nicht her, da haste Recht 😄.

LaTino

EDIT: bezeichnungen korrigiert

17.05.2017 - 14:47 Uhr

IComparer selbst sortiert nicht. Die Schnittstelle stellt lediglich die Funktion eines Vergleichs bereit, wie auch immer der aussieht. Und wer einen Vergleich braucht, um irgendwas zu tun, der kann eben eine IComparer-Implementierung verwenden. Ein Beispiel wäre ein Sortieralgorithmus: jeder Sortieralgorithmus muss in irgendeiner Weise durch die zu sortierende Liste gehen, und deren Elemente miteinander vergleichen sowie gegebenenfalls dann eben ihre Reihenfolge ändern.

Wenn du also einen Sortieralgorithmus hast, der so implementiert ist, dass man ihm einen IComparer geben kann, dann wird auch nach den Kriterien sortiert, die du im IComparer vorgegeben hast.


var sortedList = unsortedList.Sort(new MyComparer()); //sort ist der Algorithmus, dem man eine Vergleichsmethode geben kann,

Du solltest auch überlegen, ob in deinem Fall es nicht sinnvoller ist, wenn BagObject IComparable implementiert. (IComparable<T> vs. IComparer<T> ist dabei Thema vom Selbststudium 😉 ).

LaTino

Noch ein paar kleine Anmerkungen zum geposteten Code:

  • ValueOfObjects scheint eine Zahl zu sein. Wenn diese Zahl eine Anzahl ist, würde ich sie auch so nennen: ObjectCount zum Beispiel.
  • Anstatt Objekte einzeljn zu erzeugen, zu füllen und dann in eine Liste zu packen, mach doch alles in einem Aufwasch:

BagObject[] bagObjectList = Enumerable.Range(0, objectCount).Select(p => new BagObject 
{ 
    Name = GetRandomName,
    Mass = GetRandomNumber(),
    Price = GetRandomPrice()
}.ToArray();

//oder, wenn eine gute alte for-schleife angenehmer für die Augen ist:
private IEnumerable<BagObject> GenerateObjects()
{
     for(int i = 0; i < ObjectCount; i++)
         yield return new BagObject 
        { 
            Name = GetRandomName,
            Mass = GetRandomNumber(),
            Price = GetRandomPrice()
        };
}
//Anwendung: BagObject[] objectList = GenerateObjects().ToArray();

@Palin: dieser 0-Vergleich ist ein etwas verquerer Vergleich für nicht-initialisierte Werte. Würde ich ganz rauswerfen.

17.05.2017 - 12:47 Uhr

War missverständlich. "Geeignete Stelle" meint hier eine geeignete Stelle im Lebenszyklus des Windows-Forms. Überleg mal, was passiert, wenn du deine Daten zu früh an die Combobox bindest und danach erst die Daten ins Grid geschaufelt werden...genau. Dann wäre die Combobox-Auswahl wieder leer, also genau so, wie du das erlebst.

LaTino

17.05.2017 - 09:41 Uhr

Möglich ist immer alles.


//...geeignete Stelle suchen...
myGridView.Rows[specialRow].Cells[specialColumn] = new DataGridViewComboBoxCell { DataSource = {"1", "2", "3"} };

Dein Problem (wieso die Combobox leer bleibt) dürfte damit zusammenhängen, dass du das Binding nicht an einer geeigneten Stelle setzt. 's gibt dafür ein Ereignis, das beim Befüllen des Gridviews triggert.

LaTino

12.05.2017 - 10:01 Uhr

Dir ist schon klar, dass die Frage das Potenzial hat, mitlesende Web- und Desktopentwickler mit Messern zwischen den Zähnen aufeinander losgehen zu lassen, ja?

  1. Webentwickler beherrschen tendenziell mehr Technologien als Desktopentwickler, einfach, weil sie sie benötigen.

  2. Quereinsteiger steigen eher in der Webentwicklung ein. Das mag ein Grund sein, wieso man dort (gefühlt) häufiger ein komplett chaotisches Durcheinander anstelle von strukturiertem Arbeiten antrifft. Wie du sagst, fühlt man sich zeitweise in seine Anfangszeit versetzt. Aber:

  3. Du tust professionellen Webentwicklern ziemlich unrecht, wenn du glaubst, dass dieses Gefrickle in der Webenticklwung liegende Ursachen hat. Nee, das liegt an den Leuten, nicht daran, was sie tun. Wenn man das scheue Tier "full-stack developer" sucht, dann sollte man bei guten Webentwicklern zuerst suchen, da hat man noch die besten Chancen.

Aber auch hier gilt: frag zwei Entwickler und du kriegst drei Antworten.

TypeScript würde ich dir auf jeden Fall empfehlen.

LaTino
EDIT: oh, und eins noch: jeder Entwickler ist Künstler, bzw. Kunsthandwerker. Das wäre nach meiner Meinung der Unterschied zwischen Softwareentwickler und Programmierer.

11.05.2017 - 08:06 Uhr

Evaluieren gerade, was das für uns bedeutet. Sieht derzeit so aus, als ob damit quasi alle bisherigen .net-core-Projekte nicht mehr updatefähig sind[1] und damit bis zum Ende des Supports von net core 1.1 - 12 Monate nach Erscheinen von .net core 2.0 im Herbst, also in anderthalb Jahren - ersetzt werden müssen. Damit sind wir zwei Kollegen, die wir uns für netcore stark gemacht haben, quasi auf verlorenem Posten und können einpacken. .net core dürfte die nächsten Jahre hier kein Thema mehr sein. Damit, dass die Unkenrufe der Skeptiker sich bewahrheiten und wir beide aussehen wie Dorfdeppen, könnte ich noch leben, aber die Art und Weise ist schon sehr ärgerlich.

LaTino, deprimiert
[1] haben massive Abhängigkeiten auf System.Drawing sowie etliche Drittbibliotheken, für die keine Migration in Sicht ist

09.05.2017 - 07:23 Uhr

.. ob das nun für einen Anfänger "besser" verständlich ist als 5 Zeilen mehr Code... ich weiß ja nicht 😉

Naja, das einzig unverständliche ist die letzte Zeile, und die war ja im ersten Beispiel nicht drin (dort hätte sie genauso ausgesehen, wenn man Linq benutzt). Der Punkt, den ich mit "besser" meinte, ist der Verzicht auf mehrdimensionale Arrays. C# unterstützt die Arbeit damit eher halbherzig, und genau wie in C(++) ist man in jedem Fall meistens besser dran, stattdessen mit flachen Arrays zu arbeiten und sich das bisschen Mehrarbeit mit dem Indexing zu machen. Grad als Anfänger übrigens. Man müsste mal schaun, wie oft Anfänger hier im Forum beim Arbeiten mit n-Arrays oder jagged Arrays in Schwierigkeiten geraten, gefühlt ist das jedenfalls ziemlich oft 😃.

Langer Rede kurzer Sinn: @TE, wenn es geht, lass array[,] oder array[][] weg. Und meistens geht es.

LaTino

08.05.2017 - 16:31 Uhr

Das hat mir weiter geholfen, es klappt. vielen Dank!!!

Sehr schön, dann hier die bessere Variante 😉.


const int width = 64;
const int height = 240;

var flatArray = new byte[width * height];
random.NextBytes(flatArray); //<- exakt doppelt so schnell wie die Einzelbefüllung eines 2n-Arrays
var query = flatArray.Select((p, i) => new Tuple<int, int, byte>(i / height, i % height, p)).ToList();

LaTino

08.05.2017 - 13:01 Uhr

byte[,] ist ein echtes zweidimensionales Array. Das ist ein völlig anderer Typ als ein eindimensionales Array. Die Methode NextBytes der Klasse Random erwartet als Parameter ein eindimensionales Array. Daher kannst du sie nicht benutzen.

Ich lass das Folgende mal unkommentiert stehen, mit ein wenig Eigeninitiative sollte dir das helfen.


static class Extensions
{
    public static void NextBytes(this Random random, byte[,] array)
    {
        for (int i = 0; i < array.GetLength(0); i++)
        for (int j = 0; j < array.GetLength(1); j++)
        {
            array[i, j] = (byte) random.Next(0, byte.MaxValue + 1);
        }
    }
}

Schau dir auch mal die Methode GetLength(n) des zweidimensionalen Arrays an und vergleiche sie mit der Eigenschaft Length.

LaTino

05.05.2017 - 06:32 Uhr

Zuerst mal: mir rollen sich die Fußnägel hoch, wenn ich deine Klasse sehe. Wenn ein Bewerber sowas machen würde, wäre das Gespräch direkt beendet.

Zweitens: dass du nichts gefunden hast, finde ich schon sehr merkwürdig. Das Thema ist hier im Forum und auch sonst überall recht prominent.


static void Main()
{
    var serializer = new XmlSerializer(typeof(DatablockCollection));

    using (var file = File.OpenWrite("example.xml"))
    using (var writer = XmlWriter.Create(file))
        serializer.Serialize(writer, new DatablockCollection(new [] { new Datablock(), new Datablock(), new Datablock()  }));
}

public class DatablockCollection
{
    public DatablockCollection() { }
    public DatablockCollection(Datablock[] items) => Items = items;

    public Datablock[] Items { get; set; }
}

public class Datablock
{
    private const string DEFAULT_PATH = @"d:\bin";

    [XmlElement]
    public string Path { get; set; } = DEFAULT_PATH;
    [XmlElement]
    public string Name { get; set; }
    [XmlElement]
    public string LanMode { get; set; }
    [XmlElement]
    public bool Note { get; set; }
    [XmlElement]
    public string Id { get; set; }
    [XmlElement]
    public byte[] UsbRemap { get; set; } = {0x21, 0x43, 0x05};
    [XmlElement]
    public byte[] UsbConfig { get; set; } = {0x9b, 0x18, 0x00};
}

Tu dir aber bitte einen Gefallen und geh noch einmal zurück zu den Grundlagen.

LaTino

03.05.2017 - 09:04 Uhr

Zuerst einmal ist eine abstrakte Klasse kein Interface. Das mag wie Haarspalterei erscheinen, aber die Konzepte "abstrakte Superklasse" und "Interface" sollte man sauber auseinanderhalten. Schon allein, weil es da sprachlich ansonsten Missverständnisse gibt.

Zum zweiten: deine Zell-Liste ist vom Typ List<CommonCell>?

Dann:


foreach(CommonCell cell in Cells)
{
    cell.Methode(); //<- Wikipedia: Polymorphie lesen & verstehen.
}

LaTino

02.05.2017 - 09:20 Uhr

Murphy. Der nächste Versuch hat das Problem gelöst.

Für die Nachwelt: VS starten, KEIN Projekt laden.

  • Resharper Options-> Tools -> Unit Testing
  • Haken bei "Save and Restore Unit Test Sessions" entfernen

Wenn ich raten sollte, würde ich sagen, die letzte Session wurde beim Beenden fehlerhaft gespeichert, so dass er sich beim Laden dann festgefressen hat.

Problem erledigt.

LaTino

02.05.2017 - 09:12 Uhr

Ohne etwas geändert zu haben (ich schwörs!), startet mein VS2017 Pro heute morgen nicht mehr. D.h. genauer gesagt startet es noch, friert aber ein, sobald ein Projekt (irgendeins) geladen wird. Letztes Lebenszeichen ist "Continous Testing is initializing...". Ich verdächtige Resharper (Ultimate, 2017.1). Kennt jemand das Problem und weiß eventuell auch eine Lösung? Im Notfall lebe ich auch mit einem Workaround 😉.

Grüße,

LaTino

02.05.2017 - 08:52 Uhr

Eine Middleware hat immer einen Zweck der Manipulation eines Requests in der Pipeline. Hier ja gar nicht notwendig.

Erm, eigentlich manipuliert die Middleware Requests UND Responses in der Application pipeline. Insofern wäre es ohne weiteres machbar, die Antworten um zusätzliche Informationen anzureichern, und natürlich wird das auch gemacht. Der Punkt ist eher der: um HATEOAS zu implementieren, benötigt man Informationen zum Status der Applikation, die die Middleware nicht hat und auch nicht haben sollte. Wer den Status kennen muss, ist/sind der/die Controller, und aus diesem Grund passiert die Informationsanreicherung eben dort und nicht in der Middleware[1].

Grob fahrlässig verallgemeinert:
Middleware: Form der Anfragen prüfen, Form der Antworten manipulieren
EDIT: Action im [/EDIT]Controller: Inhalt der Anfragen prüfen, Inhalt der Antworten festlegen

Bei uns sieht so eine Anreicherung im Normalfall so aus:


public IActionResult Get(int id)
{
    var resultObject = DoSomething(id);
    return ResultResponse(resultObject).WithResultLink(uri);
}
//ResultResponse() ist analog zu OK() implementiert, liefert aber eine von IActionResult abgeleitete Schnittstelle, auf die die Extension WithResultLink manipulierend zugreifen kann, um den Inhalt anzureichern. Bezeichner sind im realen Leben natürlich anders.

LaTino
[1] habt ihr ja auch nicht anders behauptet, nur kam die Begründung nicht so recht rüber, meine ich.

EDIT: Abt hat natürlich recht, die Action ist, wo die, erm, Action ist. Ergänzt.