Laden...

Casten eines Array ...

Erstellt von Hajoseb vor 15 Jahren Letzter Beitrag vor 15 Jahren 1.734 Views
Hajoseb Themenstarter:in
309 Beiträge seit 2007
vor 15 Jahren
Casten eines Array ...

Hallo.

Ich komme im Moment nicht weiter.

Ich möchte "Strings.Join" nutzen ...


Strings.Join(object[], string)

jetzt habe ich aber folgendes:


List<UInt32> Code ...
...
object[] Test = (object[]) Code.ToArray();   // Zum Testen, aber hier hängt es schon :-(
...
String NeuesLiteral = Strings.Join(Test, ";");
...

Ich komme nicht dahinter, wie ich den Cast machen kann, um aus meiner List<UInt32> (bzw. UInt32[]) ein object[] für die Strings.Join(object[], string)-Methode zu bekommen ...

mfg Hajoseb

**"Zufall ist das Pseudonym Gottes, wenn er nicht selbst unterschreiben will.” **
Anatole France

49.485 Beiträge seit 2005
vor 15 Jahren

Hallo Hajoseb,

object [] aobj = new object [Code.Count];
Code.ToArray ().CopyTo (aobj, 0);

oder

Array.ConvertAll

herbivore

3.971 Beiträge seit 2006
vor 15 Jahren
  1. List<T> bietet eine CopyTo-Funktion.

  2. Casts von object[] nach string[] sind nicht möglich. Genauso nicht UInt32[] nach String[]. Soweit ich mich erinnern kann implementiert der C#-Compiler bei Arrays allerdings implizite Konvertierungen für implementierte Schnittstellen an. Ein Control[]-Array kannst du beispielsweise zu einem IDisposable[]-Array konvertieren.

Alles andere musst du mit einer Schleife selbst gestalten.

Es gibt 3 Arten von Menschen, die die bis 3 zählen können und die, die es nicht können...

49.485 Beiträge seit 2005
vor 15 Jahren

Hallo kleines_eichhoernchen,

  1. List<T> bietet eine CopyTo-Funktion.

die allerdings typisiert ist, d.h. man kann kein Object[] als Ziel angeben.

  1. Casts von object[] nach string[] sind nicht möglich. Genauso nicht UInt32[] nach String[].

Darum geht es Hajoseb ja gar nicht. Er verwendet Strings.Join und nicht String.Join und braucht daher ein Object[] und kein String[].

herbivore

3.971 Beiträge seit 2006
vor 15 Jahren

Ja gut, dann hatte ichs falsch verstanden.

Bei


Code.ToArray().CopyTo (aobj, 0);

würde ich es dennoch vorziehen, eine einfache Schleife zu verwenden. Spart man sich eine komplette Array-Konvertierung

Es gibt 3 Arten von Menschen, die die bis 3 zählen können und die, die es nicht können...

Hajoseb Themenstarter:in
309 Beiträge seit 2007
vor 15 Jahren

...
würde ich es dennoch vorziehen, eine einfache Schleife zu verwenden. Spart man sich eine komplette Array-Konvertierung

Das ist es ja gerade ... letztens hatte mir herbivore gerade Strings.Join empfohlen, aber ich hatte es nicht geschafft, diese Methode auch zu nutzen ...

object [] aobj = new object [Code.Count];  
Code.ToArray ().CopyTo (aobj, 0);  

oder

Array.ConvertAll

Bringt mir dann das ganze überhaupt noch einen Vorteil gegenüber einer "normalen" schleife mit "String += ..." oder "StringBuilder.Append" ???

mfg Hajoseb

**"Zufall ist das Pseudonym Gottes, wenn er nicht selbst unterschreiben will.” **
Anatole France

49.485 Beiträge seit 2005
vor 15 Jahren

Hallo Hajoseb,

wenn du auf einfachem Wege die String-Repräsentationen der einzelnen Elemente beliebiger Collections zu einem Strings zusammenfügen willst, ist es in der Tat etwas umständlich, diese erst in ein Objekt-Array umwandeln zu müssen. Aber du kannst das ja in einer eigenen Methode kapseln:


using System;
using System.Text;
using System.Collections.Generic;
using IUntypedEnumerable = System.Collections.IEnumerable;
using IUntypedEnumerator = System.Collections.IEnumerator;

static class App
{
   public static void Main (string [] astrArg)
   {
      List <int> list = new List <int> ();
      list.Add (1);
      list.Add (2);
      list.Add (3);
      Console.WriteLine (StringJoin (list, ", "));
   }

   public static String StringJoin (IUntypedEnumerable coll, String strDelim)
   {
      StringBuilder sbResult = new StringBuilder ();

      IUntypedEnumerator enumerator = coll.GetEnumerator ();
      try {
         if (!enumerator.MoveNext ()) { return ""; }
         sbResult.Append (enumerator.Current);
         while (enumerator.MoveNext ()) {
            sbResult.Append (strDelim);
            sbResult.Append (enumerator.Current);
         }
      }
      finally {
         IDisposable disposable = enumerator as IDisposable;
         if (disposable != null) { disposable.Dispose (); }
      }
      return sbResult.ToString ();
   }
}

herbivore

Hajoseb Themenstarter:in
309 Beiträge seit 2007
vor 15 Jahren

Hallo, herbivore. Danke 👍

Mein Ansatz gestern war dieser:


    private static String Code2String(List<UInt32> Code, String Trennzeichen)
    {
      StringBuilder NeuesLiteral = new StringBuilder();
      foreach (var Spalte in Code)
      {
        NeuesLiteral.Append(Spalte.ToString() + Trennzeichen); // Kann man auch mit 2 Append machen und ohne .ToString() ...
      }
      return NeuesLiteral.ToString().TrimEnd(Trennzeichen);
    }

Spricht etwas dagegen, dies ohne IUntypedEnumerable in IUntypedEnumerator zu machen, oder hat meine "kurze" Schreibweise einen gravierenden Nachteil, den ich als Einäugiger unter den Blinden (= Anfänger) nicht sehe?

mfg Hajoseb

**"Zufall ist das Pseudonym Gottes, wenn er nicht selbst unterschreiben will.” **
Anatole France

49.485 Beiträge seit 2005
vor 15 Jahren

Hallo Hajoseb,

ja, deine Lösung funktioniert nur List<UInt32> und wenn du sie generisch für beliebige List<T> machst, kann es bei Spalte.ToString() knallen. Aber selbst bei einer Erweiterung auf List<T> kannst du keine Arrays und anderen Collections übergeben. Das ist bei mir gerade durch IUntypedEnumerable möglich. Außerdem würde bei einer Erweiterung deines Code auf beliebige Typen, das Entfernen des Trenners nicht wirklich funktionieren. Es funktioniert schon jetzt bei dir nicht zuverlässig, wenn man als Trenner eine Ziffer(nfolge) verwendet. TrimEnd macht etwas anders als du wohl vermutest. Wenn du den überflüssigen Trenner am Ende entfernen willst und nicht wie ich vermeidest, dass er überhaupt dazugefügt wird, dann solltest du das mit String.Substring oder String.Remove machen.

herbivore

Hajoseb Themenstarter:in
309 Beiträge seit 2007
vor 15 Jahren

Oha. Ja. Kapiert.

Ich habe zu lokal (kurz) gedacht und nicht, wie du, global 👍

Auf die Idee, eine allgemein gültige Lösung zu suchen, bin ich gar nicht erst gekommen 🤔

Man lernt halt nie aus ...

mfg Hajoseb

P.S. In meinem original-Code habe ich den Trenner sogar fest auf ";" für .csv-Dateien gesetzt gehabt 🙂. Habe das andere nur in der gepsoteten Variante auf "string Trenner" erweitert ... War also noch "lokaler" auf mein Problem bezogen ...

**"Zufall ist das Pseudonym Gottes, wenn er nicht selbst unterschreiben will.” **
Anatole France

49.485 Beiträge seit 2005
vor 15 Jahren

Hallo Hajoseb,

mein Code ist ja auch nur deshalb so "aufgebläht", weil ich die foreach-Schleife manuell in eine while-Schleife umgesetzt habe, was sonst der Compiler tut, um nicht im Schleifenrumpf immer fragen zu müssen, ob ich beim ersten Element bin. Mein Code stellt ja im Prinzip nichts anders dar als eine foreach-Schleife, bei der das erste Element anders behandelt wird.

Schön wäre, wenn das C# direkt unterstützen würde, also sowas wie:

foreach (...) {
   first:
      // statments
   last:
      // statments
   others:
      // statments
}

Und das der Compiler nicht per if-Abfrage im Schleifenrumpf realisieren würde, sondern automatisch so in Code umsetzen würde, wie ich das manuell gemacht habe.

herbivore

Hajoseb Themenstarter:in
309 Beiträge seit 2007
vor 15 Jahren

Sende doch den Vorschlag malan Microsoft. Die wollen doch immer Vorschläge aus dem "Feld" 😉 und dein Wort als angesehener Forumsleiter zählt doch dann sicher etwas 8)

mfg Hajoseb

btw: Stelle dein StringJoin doch mal bei den Snippets rein. Ist doch sicher für andere auch eine gute Lösung 👍

**"Zufall ist das Pseudonym Gottes, wenn er nicht selbst unterschreiben will.” **
Anatole France

1.002 Beiträge seit 2007
vor 15 Jahren

Hallo herbivore,

Schön wäre, wenn das C# direkt unterstützen würde, also sowas wie:

foreach (...) {  
   first:  
      // statments  
   last:  
      // statments  
   others:  
      // statments  
}  

Und das der Compiler nicht per if-Abfrage im Schleifenrumpf realisieren würde, sondern automatisch so in Code umsetzen würde, wie ich das manuell gemacht habe.

Das wäre wirklich super. Mir geht es oft so, dass ich anstatt einer foreach- dann die "normale" for-Schleife verwende, weil genau das nicht funktioniert ...

Ohne mich jetzt groß im Compilerbau auszukennen, behaupte ich, dass das keine schwierige Sache ist ...

m0rius

Mein Blog: blog.mariusschulz.com
Hochwertige Malerarbeiten in Magdeburg und Umgebung: M'Decor, Ihr Maler für Magdeburg

Hajoseb Themenstarter:in
309 Beiträge seit 2007
vor 15 Jahren

Kann man eigentlich statt


      finally {
         IDisposable disposable = enumerator as IDisposable;
         if (disposable != null) { disposable.Dispose (); }
      }

Nicht auch ein


using (IUntypedEnumerator enumerator = coll.GetEnumerator ())
{
 ...
}

nutzen ???

**"Zufall ist das Pseudonym Gottes, wenn er nicht selbst unterschreiben will.” **
Anatole France

49.485 Beiträge seit 2005
vor 15 Jahren

Hallo Hajoseb,

das führt jetzt spätestens ziemlich vom Thema weg. Deshalb nur kurz und knapp: Nein, denn für using ist zwingend erforderlich, dass die benutze Klasse IDisposable implementiert oder zumindest deren Objekte implizit dahin konvertiert werden kann. Das ist bei Klassen, die IUntypedEnumerator implementieren, aber gerade nicht zwangsweise so.

herbivore