2016-06-13 6 views
0

Ich habe eine Liste von Objekten (ihre Typen sind im Voraus unbekannt). Das folgende Beispiel zeigt fest codierte Werte, aber mein tatsächlicher Code füllt die Argumentliste auf, indem er aus einer CSV-Datei liest. Ich möchte dann diese Liste von Argumenten an eine typische Methode übergeben, die nach bestimmten Parametern fragt. Also wirke ich die Elemente wie gezeigt auf die erforderlichen Typen. Ich erhalte einen Fehler:Übergeben Sie eine Objektvariable an Methode - Angegebene Umwandlung ist ungültig

Specified cast is not valid

wenn die Methode zur Laufzeit aufgerufen wird. Wie soll ich das erreichen?

var args = new List<object>(); 
     args.Add(5495); 
     args.Add("String1"); 
     args.Add(10133); 
     args.Add("String2"); 

     result = request.GetCustomer((long) args[0], (string) args[1], (int) args[2], (string) args[3]); 
+1

Der Fehler weist Sie speziell darauf hin, warum Sie die Besetzung nicht durchführen können, einschließlich des tatsächlichen Typs des Objekts und der Art, in die Sie es umsetzen möchten. Sie müssen das Objekt in den * tatsächlichen * Typ umwandeln, wenn es nicht zur Laufzeit fehlschlagen soll. – Servy

+0

Nun, ein guter Anfang wäre ein Versuch Catch Block um diese und eine Zählung, so dass Sie sehen können, welche Zeile in Ihrem CSV ist der Schuldige. – Kell

+0

@Kell Ein 'try' /' catch' Block würde das Problem nur verschleiern. Er kann den Fehler bereits sehen, er muss lediglich den Fehler in seinem Code beheben. – Servy

Antwort

4

Wenn Sie Wert hinzufügen Typen List<object>(),

args.Add(5495); 

das Element Boxed sein. Die obige Zeile bewirkt, dass 5495 von int eingerahmt wird. Um Unbox, müssen Sie args[0] explizit auf seinen Typ wie - (int)args[0]. Also, wenn Ihre Methode long als ihren ersten Parameter akzeptiert, tun Sie (long)(int)args[0]. Sie haben args[0] entpackt und dann den Wert auf long gewandelt.

+1

Vielen Dank !!! Dies behob das Problem und ich erkannte, dass ich diesen Parameter einfach als (int) anstatt als (long) interpretieren konnte. – AngieM

1

Das Problem ist, dass 5495 eine Art int haben wird und Sie versuchen, es zu einem langen zu werfen. Sie können dies auf verschiedene Arten umgehen, hier ist einer von ihnen;

Diesen ersetzen;

(long) args[0] 

mit diesem;

(long) (int) args[0] 

Dies würde nicht eine sehr nützliche Lösung jedoch sein, da Sie nie wirklich Ihre Methode einen langen Wert passieren könnte, stattdessen können Sie dies tun;

args.Add((long) 5495); 
0

versuchen Sie mit Convert.Change

 var args = new List<object>(); 
     args.Add(5495); 
     args.Add("String1"); 
     args.Add(10133); 
     args.Add("String2"); 


     long aLong = (long)Convert.ChangeType(args[0], typeof(long), CultureInfo.InvariantCulture); 

     string aStr = (string)Convert.ChangeType(args[1], typeof(string), CultureInfo.InvariantCulture); 

     int aInt = (int)Convert.ChangeType(args[2], typeof(int), CultureInfo.InvariantCulture); 
0

erstellen separate Klasse für Speicherliste Daten

class Test {

Privat lange Variable1 {get; set;}

private string Variable2 {get; set;}

private lang Variable3 {get; set;}

private string Variable4 {get; set;}

}

var args = new List();

var obj = new Test {

Variable1 = 5495,

Variable2 = "String1",

Variable3 = 10133,

Variable4 = "String2"

}

args.add (obj);

Ergebnis = request.GetCustomer (Args [0] .Variable1, Args [0] .Variable2, Args [0] .Variable3, Args [0] .Variable4);

0

Lassen Sie uns das Problem ein wenig vereinfachen.

var args = new List<object>(); 
args.Add(5495); 
var l = (long)args[0]; // throws an exception 

Was genau ist innerhalb args [0]? Eine int (weil 5495 ist ein int für den Compiler, wenn Sie möchten, dass es eine lange sein, geben Sie 5495L). Genauer gesagt, ein Boxint, weil Sie es in einem Referenz-Speicherort speichern mussten. Eine Boxed-Struktur kann nur auf die gleiche Struktur oder auf ein NULL-Zeichen dieser Struktur entpackt werden. In unserem Fall

var i = (int)args[0]; 
var nullable = (Nullable<int>)args[0]; 
var nullable1 == (int?)args[0]; 

würde alles gut funktionieren.

Sie können den Wert auf alles, mit dem es kompatibel ist, umwandeln, nachdem Sie es aus der Box genommen haben.

Sie können mehr über Boxen und Unboxing auf msdn lesen. Es ist ein sehr wertvolles Verständnis, wenn Sie C# effizient nutzen möchten.

Die Ursache für Ihr Problem ist, dass Sie eine List<object> verwenden, die das Boxen unvermeidlich machen. Es ist ziemlich selten, dass du das wirklich tun musst, du solltest wahrscheinlich deine Architektur überdenken, um es zu vermeiden.

+0

Vielen Dank für die empfohlene Lesung auf Boxen/Unboxing (vor allem auf die Leistung). Ich bin so ein Noob. Ja, dieses Design ist wahrscheinlich nicht ideal. Ich musste verschiedene Methoden mit 20-30 Parametern für jede von ihnen aufrufen, so war ich es leid, 20-30 Variablen für jede Methode -> Liste von Objekten zu definieren. Ich bin ganz Ohr wenn Sie eine bessere Empfehlung für meine Situation haben. Vielen Dank! – AngieM

+0

20-30 Parameter ist * viel *. Jede vernünftige Methode sollte wahrscheinlich nicht so viel haben. Sie sollten die meisten in einigen benutzerdefinierten Klassen, die in Ihrer Geschäftslogik sinnvoll sind, umstrukturieren und einige dieser Objekte an Ihre Methode übergeben. – Falanwe

+0

Hierbei handelt es sich hauptsächlich um Web-Service-Methoden, die bestimmte Arten von Daten erstellen (z. B. den Datensatz eines Unternehmens mit vielen Daten zum Unternehmen). Ja, wenn ich mitfahre, werde ich wahrscheinlich einige allgemeine Felder umgestalten. – AngieM