Laden...

Convert object[] to T[]

Erstellt von brainwave vor 9 Jahren Letzter Beitrag vor 9 Jahren 3.779 Views
Thema geschlossen
brainwave Themenstarter:in
436 Beiträge seit 2007
vor 9 Jahren
Convert object[] to T[]

Hallo zusammen,

ich habe hier ein object[] Array mit Items vom Typ Foo.
Nun möchte ich aus dem object[] ein Foo[] Array machen.

Folgendes funktioniert wunderbar, allerdings denke ich, dass es einen sauberen Weg gibt als eine Kopie anzulegen..


Type orginType =obj[0].GetType();
Array newObj = Array.CreateInstance(orginType, obj.Length);
Array.Copy(obj, newObj, newObj.Length);

49.485 Beiträge seit 2005
vor 9 Jahren

Hallo brainwave,

den Typ eines Objekts kann man nachträglich nicht ändern. Es ist also aus meiner Sicht unumgänglich, ein neues Objekt (mit dem alten Inhalt) zu erzeugen. Es sei denn, ich übersehe irgendeine Spezialität bei Arrays.

herbivore

brainwave Themenstarter:in
436 Beiträge seit 2007
vor 9 Jahren

Eigentlich sollte das hier auch funktionieren aber tut es nicht:


          Type orginType = obj)[0].GetType();
                Array arr = Array.ConvertAll(obj, elem => Convert.ChangeType(elem, orginType));

arr bleibt weiterhin object[]

49.485 Beiträge seit 2005
vor 9 Jahren

Hallo brainwave,

weil du die konkreten Typen dabei nicht zur Compilezeit bekannt sind.

Es wird also wohl Array.ConvertAll<object, object> verwendet. Es müsste aber Array.ConvertAll<object, Foo> verwendet werden. Wenn du die Typen explizit angibst, sollte es funktionieren.

herbivore

brainwave Themenstarter:in
436 Beiträge seit 2007
vor 9 Jahren

Funktioniert leider auch nicht..

49.485 Beiträge seit 2005
vor 9 Jahren

Hallo brainwave,

du solltest wissen, dass "funktioniert nicht", keine ausreichende Problembeschreibung ist, siehe [Hinweis] Wie poste ich richtig? Punkt 5.

herbivore

PS: Ich habe es ausprobiert: Wenn man explizit Array.ConvertAll<object, Foo> verwendet, dann bekommt man ein Objekt vom Typ Foo[] heraus.

5.941 Beiträge seit 2005
vor 9 Jahren

Hallo zusammen

@herbivore Man muss ja den Typ nicht ändern, nur den Zugriff darauf per Cast. Der unterliegende Typ muss natürlich tatsächlich ein Foo sein.

LINQ hat ein .Cast<T>, damit funktionierts, bei den beschriebenen Bedingungen.


object[] foos = new Foo[] { new Foo(), new Foo(), };
Foo[] finalyFoos = foos.Cast<Foo>().ToArray();

Gruss Peter

--
Microsoft MVP - Visual Developer ASP / ASP.NET, Switzerland 2007 - 2011

brainwave Themenstarter:in
436 Beiträge seit 2007
vor 9 Jahren

Mit "funktioniert nicht" war "arr bleibt weiterhin object[]" gemeint. Oben bereits erwähnt.

5.941 Beiträge seit 2005
vor 9 Jahren

Hallo

Mit "funktioniert nicht" war "arr bleibt weiterhin object[]" gemeint. Oben bereits erwähnt.

Ja, weil du es dem Typ "Array" zuweist, der darunterliegend ein object[] ist, untypisiert.

Gruss Peter

--
Microsoft MVP - Visual Developer ASP / ASP.NET, Switzerland 2007 - 2011

brainwave Themenstarter:in
436 Beiträge seit 2007
vor 9 Jahren

@Peter,

das Problem ist, dass Foo erst zur Laufzeit bekannt ist. Meine Schnittstelle erwartet nur ein object[]:

void DoIt(object[] objArr)
{...}

Somit kann ich erst zur Laufzeit ermittel vom welchem Typ dieses objArr ist bzw. die Items sind.

49.485 Beiträge seit 2005
vor 9 Jahren

Hallo brainwave,

den statischen Typ einer Variable / eines Ausdrucks kann man man nur ändern, wenn der Typ zur Compilezeit bekannt ist. Das hatten wir schon in Objekt auf (statischen) Typ eines anderen Objekts casten besprochen.

Das sind Grundlagen, siehe [Hinweis] Wie poste ich richtig? Punkt 1.1.1.

Hallo Peter Bucher,

Man muss ja den Typ nicht ändern, nur den Zugriff darauf per Cast. Der unterliegende Typ muss natürlich tatsächlich ein Foo sein.

letzteres scheint hier aber nicht der Fall zu sein. Zumindest habe ich die Beschreibung so verstanden. brainwave schreibt, er habe ein object[] in dem Elemente vom Typ Foo eingetragen sind. Das ist und bleibt dann aber ein object[]. Er schreibt nicht, er habe ein Foo[] das als object[] übergeben wird (wobei das auch nicht so ohne weiteres gehen würde, denn sonst könnte man ja auch Objekte mit anderen Typen als Foo als Elemente zuweisen).

Ja, weil du es dem Typ "Array" zuweist, der darunterliegend ein object[] ist, untypisiert.

Nein, weil er Array.ConvertAll<object, object> statt Array.ConvertAll<object, Foo> verwendet.

herbivore

brainwave Themenstarter:in
436 Beiträge seit 2007
vor 9 Jahren

den statischen Typ einer Variable / eines Ausdrucks kann man man nur ändern, wenn der Typ zur Compilezeit bekannt ist

Ist das tatsächlich so?


Type orginType = obj[0].GetType();
var item = Convert.ChangeType(obj)[0], orginType);

Dann müsste "item" vom Typ object sein, ist aber Foo. Dh. die Umwandlung ist korrekt.

49.485 Beiträge seit 2005
vor 9 Jahren

Hallo brainwave,

du musst zwischen dem Typ der Variable und dem Typ des referenzierten Objekts unterscheiden.

Auch wieder Grundlagen. Bitte beachte [Hinweis] Wie poste ich richtig? Punkt 1.1.1.

Der Typ der Variable müsste nach Lage der Dinge Object sein.

herbivore

brainwave Themenstarter:in
436 Beiträge seit 2007
vor 9 Jahren

Nein, der Typ der Variable ist nach Convert.ChangeType() Foo und nicht Object.
Foo ist im Code niergends erwähnt, also zur Compilezeit nicht bekannt.

Damit ihr mich nicht missversteht: das Objekt objArr ist selbst vom Typ object[]. Die darin enthalteten Items sind vom Typ Foo.

49.485 Beiträge seit 2005
vor 9 Jahren

Hallo brainwave,

ich habe folgenden Code verwendet


static class App
{
   public static void Main ()
   {
      object [] obj = new object [1];

      obj[0] = new Foo ();

      Type orginType = obj[0].GetType();
      var item = Convert.ChangeType(obj[0], orginType);
   }
}

public class Foo
{
}

und mirs im Reflector angeschaut. Die Variable ist wie erwartet vom Typ Object. Das enthalte Objekt ist vom Typ Foo. Im Prinzip passiert durch den Code nichts anderes als durch:

var item = obj[0];

Beide Zuweisungen laufen darauf hinaus, dass der statische Typ Object und der dynamische Typ Foo ist.

Solange du das munter durcheinander schmeißt, wirst du nicht weit(er) kommen.

Das sind nun wirklich Grundlagen. Bitte beachte wie schon gesagt [Hinweis] Wie poste ich richtig? Punkt 1.1.1.

herbivore

Thema geschlossen