Laden...

C# 8 mit .NET Full / .NET Core 3.0 mit WinForms

Erstellt von peterpan4711 vor 4 Jahren Letzter Beitrag vor 4 Jahren 2.697 Views
Thema geschlossen
Hinweis von gfoidl vor 4 Jahren

Abgeteilt von Performanterer Weg in einem Byte Array ein anderes (mehrfach) zu suchen

P
peterpan4711 Themenstarter:in
19 Beiträge seit 2019
vor 4 Jahren
C# 8 mit .NET Full / .NET Core 3.0 mit WinForms

Ist es denn möglich, .Net Core 3.0 auch bei WinForms Anwendungen zu nutzen? Ich hab ein Testprojekt auf Consolen basis gemacht dort funktioniert die Klasse wunderbar.

Nun wollte ich die Klasse in mein eigentliches Projekt importieren jedoch kann ich dort .NET Framesworks statt Core nutzen und dort ich finde nirgendwo eine Preview von .NET 5

Fehlermeldungen im Anhang.

Nachtrag:
Ich habe gesehen man kann beim Erstellen des Projektes auswählen ob .NET Framework oder .NET Core.

  1. Bekomme ich das im Nachgang noch geändert?
  2. Wo liegen jetzt die Unterschiede? Bisher habe ich alles auf .NET Framework gemacht.

Nachtrag 2:
Okay ein .NET Core WinForms Projekt hat kein GUI Designer... Wie stelle ich das jetzt am sinnvollsten an?

Nachtrag 3:
Mit dieser Preview Extension: Windows Forms Designer Release Notes
Läuft dann auch der Designer wieder!

Bleibt nur noch die Frage ob man nachträglich von .NET Framework auf .NET Core wechseln kann.

Nachtrag 4:
Ich glaube niemand möchte .NET Core in Forms aktuell nutzen. Die Auswahl in der Toolbox geht gegen null, Sachen wie eine Groupbox sind nicht vorhanden.

Ist die Klasse (sinnvoll) unter .NET 4.8 zu betreiben?

T
2.219 Beiträge seit 2008
vor 4 Jahren

@peterpan4711
Die Klasse müsste sich auch auf .NET Framework 4.8 portieren lassen.
Dann müsste man ggf. mal schauen ob der Syntax noch passt oder ob man diesen auch noch anpassen muss.

Dann kannst du aber nicht die Verarbeitszeit von gfoidl erreichen, da eben in .NET Core eingie Optimierungen eingeflossen sind die erheblicher Natur sind.

T-Virus

Developer, Developer, Developer, Developer....

99 little bugs in the code, 99 little bugs. Take one down, patch it around, 117 little bugs in the code.

P
peterpan4711 Themenstarter:in
19 Beiträge seit 2019
vor 4 Jahren

Leider kommen ja die Fehler wie oben im Bild zu sehen.
Der ReadOnlyMemory Fehler ist gefixt, da fehlte der Verweis.

Wenn es statt 1000ms 10000ms dauert ist das kein Problem für mich. Vorher waren es Stunden mit meiner Methode.

Ich verstehe nur nicht wie ich die Klasse umschreiben kann, gerade im bezug auf die Ranges die die meisten Probleme machen.

Falls es einen Weg gibt .NET Core sauber zu nutzen mit Forms Designer dann wäre ich auch da dabei - jedoch scheint alles noch sehr fehlerhaft zu sein. Ist ja nunmal Preview.

Nachtrag:
Ist es denn möglich System.Range mit .NET 4.8 zu nutzen? Denn "#nullable enable" wirft keinen Fehler mehr, "NotNullWhen" aber schon. Range eh...

LangVersion ist auf 8.0:

    <LangVersion>8.0</LangVersion>
T
2.219 Beiträge seit 2008
vor 4 Jahren

System.Range scheint es nur in .NET Core zu geben.
Entsprechend müsstest du schauen, wie du dieses ersetzt.
Im einfachsten Fall, musst du nur die Start- und Länge/Ende angeben.
Dies müsstest du aber auch berechnen können.

Den Code kann ich mir erst heute Abend wieder anschauen und versuchen zu portieren. 😦

T-Virus

Developer, Developer, Developer, Developer....

99 little bugs in the code, 99 little bugs. Take one down, patch it around, 117 little bugs in the code.

P
peterpan4711 Themenstarter:in
19 Beiträge seit 2019
vor 4 Jahren

Ja das hab ich versucht, komme da aber nicht weiter. Ich hab mal ganz primitiv versucht "0, End" oder "Start, End" jedoch nicht mit dem gewünschtem Ergebnis.

6.911 Beiträge seit 2009
vor 4 Jahren

Hallo peterpan4711,

habs vom anderen Thema abgeteilt, da es doch nicht mehr so ganz passte 😉

Falls es einen Weg gibt .NET Core sauber zu nutzen mit Forms Designer dann wäre ich auch da dabei

Die Designer-Kinder 🙂

Möglichkeiten:* die Logik (die andere Methode) in ein .NET Standard-Projekt auslagern (da gehen aber auch keine Ranges -- siehe unten, außer wird per Multi-Targeting für .NET Core 3.0 und .NET Standard 2.0 gemacht) und dann im WinForms-Projekt verwenden (so kann später zu .NET Core gewechselt werden, wenn der Designer besser wird)

  • statt WinForms WPF verwenden
  • auf den Designer verzichten und den Code selbst schreiben (mehr macht der Designer auch nicht -- guck mal in die *.Designer.cs od. wie die heißt)
  • mit einem .NET Full-WinForms-Projekt das Layout erzeugen und die Designer-Dateien im .NET Core-Projekt verwenden (am besten durch Verlinkung)
  • ...

es gibt doch viele Möglichkeiten

Ist es denn möglich System.Range mit .NET 4.8 zu nutzen?

C# 8 wird von .NET Full nicht (offiziell) unterstützt*.
Die Schreibweise start..end wandelt der C# 8-Compiler um zu


var rande = new Rande(start, end);

und verwendet dann diesen Typen für die Wahl der passenden Überladung aus.

wie ich die Klasse umschreiben kann, gerade im bezug auf die Ranges die die meisten Probleme machen

Nimm einfach die "normalen" Slice-Methoden, die Start-Index und Länge nehmen. Dabei halt die Länge vorher berechnen. Dieser Schritt entfällt nämlich durch Verwendung von Ranges, die den Code "netter" machen (falls C# 8 verwendet werden kann).
Wenn du den Code soweit verstanden hast, so sollte das kein Problem sein...und bitte nicht raten wie im letzten Beitrag, sondern :rtfm: und schauen welche Parameter benötigt werden --> das geht schneller und ist zielführender. Den Code hast du schon erhalten, daher überlass ich das jetzt dir 😉

* das meiste in C# 8 ist Syntax-Zucker, aber es gibt auch Features wie "default interfaces" die eine Änderung der Runtime nach sich zogen, daher ist nur .NET Core (Mono, etc. weiß ich nicht, gehe aber schon davon aus) darauf vorbereitet.

mfG Gü

Stellt fachliche Fragen bitte im Forum, damit von den Antworten alle profitieren. Daher beantworte ich solche Fragen nicht per PM.

"Alle sagten, das geht nicht! Dann kam einer, der wusste das nicht - und hat's gemacht!"

T
2.219 Beiträge seit 2008
vor 4 Jahren

Hab mal aus dem Projekt von gfoidl die BinaryArrayExtension in mein .NET 4.8 Projekt übernommen.
Die Geschwindigkeit bei beiden schwankt nur minimal, komme auf Zeiten um die 80-160ms.
Die Portierung war nur die Umrechnung der Range Ende zu Länge, dann klappt es ohne Probleme.

@peterpan4711
Du musst nur die die Länge der Range.Item1/Item2 ermitteln.
Eigentlich sind nur ca. 3-4 Stellen anzupassen, ist nicht so schwer 😃

T-Virus

Developer, Developer, Developer, Developer....

99 little bugs in the code, 99 little bugs. Take one down, patch it around, 117 little bugs in the code.

4.931 Beiträge seit 2008
vor 4 Jahren

Die Range-Struktur (sowie Index) kannst du auch einfach selber implementieren, s. z.B. C# 8: Indexes and Ranges. Oder statt Index kannst du auch einfach int benutzen.

PS: @gfoidl, du hast dich vertippt bei

var rande = new Rande(start, end);

😉

PPS: Schon 2013 hat jemand einen Range-Datentyp in C# implementiert: Ranges in C#.

6.911 Beiträge seit 2009
vor 4 Jahren

Hallo Th69,

ui, da war ich gleich zwei Tasten daneben 😃 Danke für den Hinweis (da ich es gerade lustig finde, editiere ich es oben nicht...)

Zum PPS: ich denke diese beiden Typen sind so trivial dass diese schon woanders vorher in C# implementiert wurden (z.B. in meine Codes, da ich das von Fortran und Matlab so gewohnt war). Mag jedoch sein, dass dies der erste explizite Artikel darüber war.

Hallo zusammen,

Range und Index sind im Grunde recht simple Typen, die wie von Th69 angemerkt recht einfach selbst implementiert werden können.
Die Verwendung von denen in .NET Core 3.0 hat jedoch den Vorteil, dass der (Ryu)JIT diese besonders behandeln kann und besseren Maschinencode erstellt. Sofern das von Bedeutung ist.

mfG Gü

Stellt fachliche Fragen bitte im Forum, damit von den Antworten alle profitieren. Daher beantworte ich solche Fragen nicht per PM.

"Alle sagten, das geht nicht! Dann kam einer, der wusste das nicht - und hat's gemacht!"

4.931 Beiträge seit 2008
vor 4 Jahren

Und falls das nicht klar genug von mir beschrieben wurde. So braucht der Code nicht geändert zu werden und kann mit diesen eigenen Implementierungen dann einfach für .NET 4.x verwendet werden (und bei einem Umstieg zu .NET Core benutzt man dann eben die dortige Implementierung) - so wie es z.B. auch nachträglich für LINQ für .NET 2.x gemacht wurde.

P
peterpan4711 Themenstarter:in
19 Beiträge seit 2019
vor 4 Jahren

Ich bin jetzt dem Beispeil von dieser Seite gefolgt: C# 8: Indexes and Ranges und habe meine Software um eine Klasse "Extensions" erweitert:

static class Extensions
    {
        public readonly struct Index
        {
            private readonly int _value;

            public int Value => _value < 0 ? ~_value : _value;
            public bool FromEnd => _value < 0;

            public Index(int value, bool fromEnd)
            {
                if (value < 0) throw new ArgumentException("Index must not be negative.", nameof(value));

                _value = fromEnd ? ~value : value;
            }

            public static implicit operator Index(int value)
              => new Index(value, fromEnd: false);
        }

        public readonly struct Range
        {
            public Index Start { get; }
            public Index End { get; }

            private Range(Index start, Index end)
              => (Start, End) = (start, end);

            public static Range Create(Index start, Index end) => new Range(start, end);
            public static Range FromStart(Index start) => new Range(start, new Index(0, fromEnd: true));
            public static Range ToEnd(Index end) => new Range(new Index(0, fromEnd: false), end);
            public static Range All() => new Range(new Index(0, fromEnd: false), new Index(0, fromEnd: true));
        }



        public static int get_IndexerExtension(this int[] array, Index index) =>
          index.FromEnd ? array[array.Length - index.Value] : array[index.Value];

        public static int get_IndexerExtension(this Span<int> span, Index index) =>
          index.FromEnd ? span[span.Length - index.Value] : span[index.Value];

        public static char get_IndexerExtension(this string s, Index index) =>
          index.FromEnd ? s[s.Length - index.Value] : s[index.Value];

        public static Span<int> get_IndexerExtension(this int[] array, Range range) =>
          array.Slice(range);

        public static Span<int> get_IndexerExtension(this Span<int> span, Range range) =>
          span.Slice(range);

        public static string get_IndexerExtension(this string s, Range range) =>
          s.Substring(range);

        public static Span<T> Slice<T>(this T[] array, Range range) => array.AsSpan().Slice(range);

        public static Span<T> Slice<T>(this Span<T> span, Range range)
        {
            var (start, length) = GetStartAndLength(range, span.Length);
            return span.Slice(start, length);
        }

        public static string Substring(this string s, Range range)
        {
            var (start, length) = GetStartAndLength(range, s.Length);
            return s.Substring(start, length);
        }

        private static (int start, int length) GetStartAndLength(Range range, int entityLength)
        {
            var start = range.Start.FromEnd ? entityLength - range.Start.Value : range.Start.Value;
            var end = range.End.FromEnd ? entityLength - range.End.Value : range.End.Value;
            var length = end - start;

            return (start, length);
        }
    }

Und habe es dann so versucht:

ReadOnlyMemory<byte> memorySlice = source.AsMemory(Range.Create(start, end));

jedoch bekomme ich dann den Fehler "Konvertierung von Extensions.Range in int nicht möglich"

In dem Artikel steht jedoch noch man solle the ranges.cs von C# 8 zum Projekt hinzufügen - > Die gibts bei Github unter der Verklinkung leider nicht mehr.

T
2.219 Beiträge seit 2008
vor 4 Jahren

@peterpan4711
Hier der richtige Link.

Range.cs

T-Virus

Developer, Developer, Developer, Developer....

99 little bugs in the code, 99 little bugs. Take one down, patch it around, 117 little bugs in the code.

P
peterpan4711 Themenstarter:in
19 Beiträge seit 2019
vor 4 Jahren

Danke.

nun bekomme ich bei der Schreibweise von gfoidl folgende Fehler:

CS0656	Der vom Compiler angeforderte Member "System.Range..ctor" fehlt.	
CS1503	Argument "2": Konvertierung von "System.Range" in "int" nicht möglich.	

Bei folgendem Code:

ReadOnlyMemory<byte> memorySlice = source.AsMemory(range.Item1..range.Item2);
T
2.219 Beiträge seit 2008
vor 4 Jahren

@peterpan4711
Das liegt daran, dass in .NET 4.8 eben der Syntax mit .. nicht enthalten ist.
Hier musst du .. nur durch , ersetzen, damit die Parameter mitgegeben werden.
Dann hast du aber vermutlich, wie es bei mir der Fall ist, wieder start als ersten und length als zweiten Parameter.
Ich hatte diese bei mir umgerechnet, die Ranges habe ich an den 2-3 Stellen entfernt und eben durch die Länge ersetzt.
Ich kann heute Abend mal schauen, ob es auch mit geht.

T-Virus

Developer, Developer, Developer, Developer....

99 little bugs in the code, 99 little bugs. Take one down, patch it around, 117 little bugs in the code.

P
peterpan4711 Themenstarter:in
19 Beiträge seit 2019
vor 4 Jahren

Wenn ich die .. duch , ersetze bekomm ich direkt eione Exception:

System.ArgumentOutOfRangeException: "Das angegebene Argument liegt außerhalb des gültigen Wertebereichs."

Auf:

ReadOnlyMemory<byte> memorySlice = source.AsMemory(range.Item1,range.Item2);

Wie rechnest Du das um?

6.911 Beiträge seit 2009
vor 4 Jahren

Hallo peterpan4711,

jetzt sind wir endgültig zu [Hinweis] Wie poste ich richtig? (Grundlagen) abgerutscht.

Die ArgumentOutOfRangeException bekommst du, da nicht das Ende, sondenr die Länge erwartet wird. Das sind aber wirklich absolute Grundlagen.

Mach es dir doch nicht komplizierter als es sein muss.
Probier den Code zu verstehen (wenn du schon den fertigen Code erhalten hast) und pass die zwei, drei Zeilen mit Range an, so dass es funktioniert. Es ist nicht nötig Range und Index so kompliziert nachzubauen (und wenn schon nimm den richtigen Link (siehe meinen Beitrag oben) als Vorlage und nicht irgendetwas das nicht den Code-Konventionen entspricht), da vieles aus diesen Typen eh nicht benötigt wird.
Weiters kann nur der C# 8 Kompiler die Schreibweise .. verstehen um daraus eine Range zu bilden. Das wurde alles schon erwähnt und wir drehen uns im Kreis (daher hab ich das Thema jetzt geschlossen).

Statt


ReadOnlyMemory<byte> slice = buffer.AsMemory(start..end);

schreibst du einfach


int length = end - start;
ReadOnlyMemory<byte> slice = buffer.AsMemory(start, length);

Das wars auch schon. Hättest du in die :rtfm: geguckt, so solltest du diese Lösung selbst gefunden haben.

Jetzt mach ich mir schon die Mühe Code zu erstellen (auch weil es mich interessiert hat) und um ein paar neue Features von C# 8 und .NET Core 3 zu zeigen, die auch so annotiert wurde in der Beschreibung dazu, so könntest du dir wenigstens die Mühe machen den gelieferten Code, der nicht einmal recht aufwändig und lang ist, zu verstehen um so die restlichen Probleme zu lösen. Aber stattdessen wird mit Trivial-Fehlern das Forum zur Lösungssuche erneut bemüht, anstatt es als Chance zu sehen etwas zu Recherchieren und etwas Lernen zu können...

mfG Gü

Stellt fachliche Fragen bitte im Forum, damit von den Antworten alle profitieren. Daher beantworte ich solche Fragen nicht per PM.

"Alle sagten, das geht nicht! Dann kam einer, der wusste das nicht - und hat's gemacht!"

Thema geschlossen