Currying von Typ-Parametern bei generischen Extension-Methoden.
-
Hallo liebe liebende (
),
Ich habe eine kleine Frage zu generischen Extension-Methoden und der Spezifizierung der Typ-Parameter beim Aufruf derselben. Zur Veranschaulichung sei folgender Code gegeben:
static class Test { public static IList<TargetType> WhyDoesThisWork<TargetType>(this IList<TargetType> Forward) { return Forward; } public static IList<TargetType> WhyDoesThisNOTWork<SourceType, TargetType>(this IList<SourceType> This) where TargetType: SourceType { throw new NotImplementedException(); } } class Program { static void Main(string[] args) { IList<string> Strings = null; IList<object> Objects = new List<object>(); Strings.WhyDoesThisWork(); //Strings = Objects.WhyDoesThisNOTWork<string>(); Strings = Objects.WhyDoesThisNOTWork<object, string>(); } }
Für eine Extension-Methode wie
WhyDoesThisWork
mit einem Typ-Parameter muss die Typ-Parameter nicht angegeben werden, scheinbar findet eine Art automatische Zuordnung bzw. Currying statt. Nun wollte ich in anderem Zusammenhang eine Extension-Methode ähnlichWhyDoesThisNOTWork
definieren, welche zwei Typ-ParameterTargetType
undSourceType
mit einem Constraintwhere TargetType: SourceType
hat.Bei der Anwendung dieser Extension-Methode ist es jedoch unerwartet notwendig, dass man nicht nur einen Typ-Parameter
TargetType
, sondern gleich beide explizit angibt. Wieso muss man auf Zeile 28 im Listing den ersten Typ-Parameterobject
angeben, wenn dieser sowieso Rückgeschlossen werden muss? Ist das eine Einschränkung der Sprache oder habe ich etwas falsch definiert? Ich habe versucht, den gleichen Sachverhalt mit Visual Basic.NET zu formulieren, aber mir ist der Compiler abgeschmiertMfG / schönes Wochenende :p
-
Currying? Seh ich nicht.
Nun der TargetType ist für C# nicht ableitbar, daher muss du alle Typeparameter angeben. Sonst wird aus 2 Stellen schnell man eine Stelle und dies wiederum in Mehrdeutigkeit.
-
Zeus schrieb:
Nun der TargetType ist für C# nicht ableitbar, daher muss du alle Typeparameter angeben. Sonst wird aus 2 Stellen schnell man eine Stelle und dies wiederum in Mehrdeutigkeit.
Bei einem Argument ist er aber ableitbar. Wieso nicht bei zwei? Immerhin wird der SourceType doch in Form des
this
übergeben; dass man den TargetType noch spezifizieren muss, leuchtet schon ein.
-
Wenn die Ableitung nach ähnlichen Regeln wie bei C++ funktioniert, könnte es helfen die Parameter umzutauschen (erst den target-Typ).
-
CStoll schrieb:
Wenn die Ableitung nach ähnlichen Regeln wie bei C++ funktioniert, könnte es helfen die Parameter umzutauschen (erst den target-Typ).
/rant/ schrieb:
Zeus schrieb:
Nun der TargetType ist für C# nicht ableitbar, daher muss du alle Typeparameter angeben. Sonst wird aus 2 Stellen schnell man eine Stelle und dies wiederum in Mehrdeutigkeit.
Bei einem Argument ist er aber ableitbar. Wieso nicht bei zwei? Immerhin wird der SourceType doch in Form des
this
übergeben; dass man den TargetType noch spezifizieren muss, leuchtet schon ein.Leider hat Herr Anders Hejlsberg sich nicht an C++ orientiert und somit Extensions noch mehr verkrüppelt
Geht es, sieht man an C++, aber die bei MS haben sich anders entschieden,Gott weiss, warum.
-
Ich bin sehr nahe daran, die Extension-Methoden aus dem Projekt zu kippen. In der aktuellen Form bringen die praktisch nur noch Nachteile mit sich. Von der statischen Bindung will ich gar nicht erst anfangen.
Desweiteren: Warum erlaubt C# keine nested interfaces, aber andere Sprachen schon? Überall künstliche Einschränkungen, das nervt mich.
Die Ausdrucksstärke der .NET-Sprachen hat sich nicht so entwickelt, wie ich es mir erhofft hatte
Trotzdem vielen Dank.
-
/rant/ schrieb:
Ich bin sehr nahe daran, die Extension-Methoden aus dem Projekt zu kippen. In der aktuellen Form bringen die praktisch nur noch Nachteile mit sich. Von der statischen Bindung will ich gar nicht erst anfangen.
Desweiteren: Warum erlaubt C# keine nested interfaces, aber andere Sprachen schon? Überall künstliche Einschränkungen, das nervt mich.
Die Ausdrucksstärke der .NET-Sprachen hat sich nicht so entwickelt, wie ich es mir erhofft hatte
Trotzdem vielen Dank.
Bald kommt Scala for .Net
-
Zeus schrieb:
Bald kommt Scala for .Net
Ich habe mal gedacht, dass C++/CLI das Scala in der .NET-Welt werden könnte. War dann nicht ganz so, leider. Ich schreibe jetzt dann meine eigene Sprache, wenn es so weiter geht. C++0x für .NET :trollface:
-
Hallo,
ich verstehe nicht wo du das Problem siehst, bzw. wieso unverständlich ist wieso zweite Variante nicht ohne explizite Typangaben funktioniert.
Als Parameter wird nur der SourceType übergeben, der wäre sogar automatisch ermittelbar, aber TargetType ist unmöglich festzulegen. Der wird nur als Rückgabetyp verwendet und der gehört in praktisch keiner Sprache zur Methodensignatur, kann also nicht verwendet werden. Und auch das Constraint schränkt den Typen ja nicht genug ein, da jede Ableitung von SourceType, bzw. Implementierung wenn es ein Interface wäre, gültig ist. Welchen Typ soll TargetType also haben?
Sprich TargetType ist nicht automatisch ermittelbar, also müssen die Typparameter angegeben werden. Und nur einen von mehreren Typparameter angeben zu müssen geht syntaxtechnisch nicht und das ist auch gut so. Sonsts gäbs wahrscheinlich solchen Code
SuperGenericMethod<,,Typ1,,,,Typ2,Typ3,,>()
-
@Zwergli
Seine meßlatte ist C++. Und es geht sehr wohl, wenn du alle ableitbaren Typeparameter zum Schluss deklarierst, kannst du Sie beim Anwenden auslassen. Das C# nicht kann,... hab ich doch geschrieben. Mussu genauer lesen!
-
Trotzdem fragt er im Post danach doch wieso ein Parameter abgeleitet werden kann, bei zwei aber nicht. Darauf hab ich genauer geantwortet.
Mussu genauer lesen!
Der Vergleich C# und C++ hinkt so oder so - da Generics und Templates haben nicht grundlos unterschiedliche Namen - es sind auch unterschiedliche Dinge.
-
Nagut dann können wir Java nehmen.
-
Wofür?
.Net Generics und Java Generics sind ja technisch wieder zwei ziemlich unterschiedliche Dinge. Die .Net VM kennt Generics, die Java VM nicht. Dort haut der Compiler per Type Erasuere jegliche Generizität raus ausm Code.
-
/rant/ schrieb:
Die Ausdrucksstärke der .NET-Sprachen hat sich nicht so entwickelt, wie ich es mir erhofft hatte
Ich will dir ja nicht zu nahe treten, aber deine letzten paar Threads zum Ausloten was C# kann, die liefen oft in die Richtung: "Aber in C++ geht das!". Wieso nimmst du eigentlich nicht gleich C++? Du versuchst sehr template-lastige Sachen von C++ nach C# zu hieven und das klappt halt nicht wirklich gut.
-
Also bist du mit F# zufrieden?
open System module TestClass = type Box<'a>() = class end;; module TestExtension = open TestClass type Box<'a> with member this.convert<'b when 'b :> System.Object>() = this ;; open TestClass open TestExtension let box = new Box<String>() let result = box.convert<DateTime>()
.method public static class Program/TestClass/Box`1<!!a> Box`1.convert<a,b>(class Program/TestClass/Box`1<!!a> A_0) cil managed ^^^ zwei Type-Parameter { .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationArgumentCountsAttribute::.ctor(int32[]) = ( 01 00 02 00 00 00 01 00 00 00 00 00 00 00 00 00 ) // Code size 3 (0x3) .maxstack 3 IL_0000: nop IL_0001: ldarg.0 IL_0002: ret } // end of method TestExtension::Box`1.convert
-
GPC schrieb:
/rant/ schrieb:
Die Ausdrucksstärke der .NET-Sprachen hat sich nicht so entwickelt, wie ich es mir erhofft hatte
Ich will dir ja nicht zu nahe treten, aber deine letzten paar Threads zum Ausloten was C# kann, die liefen oft in die Richtung: "Aber in C++ geht das!". Wieso nimmst du eigentlich nicht gleich C++? Du versuchst sehr template-lastige Sachen von C++ nach C# zu hieven und das klappt halt nicht wirklich gut.
Du hast schon recht mit deiner Aussage. Schlussendlich geht es um die Frage, was wo machbar ist. C++ kennt kein Reflection.Emit, was zentral ist. C++/CLI ist tot und unterstützt kein WPF. C# hat keine Templates. Aber am Ende des Tages ist wohl C# die einzige Sprache, womit ein hoch dynamisches System noch überhaupt sinnvoll realisierbar ist.
-
/rant/ schrieb:
Aber am Ende des Tages ist wohl C# die einzige Sprache, womit ein hoch dynamisches System noch überhaupt sinnvoll realisierbar ist.
Öh. Wenn das die einzige Anforderung ist, dann geht erstmal viel.
Java, Python, C++ + Lua, C++ + LLVM, ...