Als Jon Skeet sagte und Eric Lippert gesichert, Konstrukteure für generische Klassen in C# ihre Typen aus ihrer Parameter oder die Art der nicht ableiten kann Variable, der die Konstruktion zugeordnet ist. Das Einstiegsmuster, wenn diese Art von Verhalten nützlich ist, ist normalerweise eine statische generische Fabrikmethode, die ihren eigenen generischen Typ von ihren Parametern ableiten kann. Tuple.Create()
ist ein Beispiel; geben Sie ihm eine Liste von Parametern bis zu 8, und es wird ein stark typisiertes generisches Tuple mit diesen Parametern als Datenfelder erstellt. Dies funktioniert jedoch nicht gut für Ihren Fall.
Wenn die Variable lokal ist, können Sie auch umgekehrt vorgehen. verwenden variable Typinferenz über das var
Stichwort:
var Prototypes = new List<double[][]>();
Dies ist, wie das C# Team auf der Eingabe zu reduzieren entschieden, als Variablen Instanziieren. Lokale Variablen werden viel häufiger als Instanzvariablen erstellt und geändert. Dieser Ansatz lässt C# -Code ein wenig wie JavaScript aussehen.
Wie Jon gezeigt hat, ist es möglich, das Chaos zu verstecken, aber Sie werden mehr Chaos in diesem Prozess verursachen. Hier ist eine andere Möglichkeit mit .NET 3.5/4.0s Ausdruckeigenschaften:
public static string GetName(this Expression<Func<object>> expr)
{
if (expr.Body.NodeType == ExpressionType.MemberAccess)
return ((MemberExpression) expr.Body).Member.Name;
//most value type lambdas will need this because creating the Expression
//from the lambda adds a conversion step.
if (expr.Body.NodeType == ExpressionType.Convert
&& ((UnaryExpression)expr.Body).Operand.NodeType
== ExpressionType.MemberAccess)
return ((MemberExpression)((UnaryExpression)expr.Body).Operand)
.Member.Name;
throw new ArgumentException(
"Argument 'expr' must be of the form()=>variableName.");
}
public static void InitializeNew(this object me, params Expression<Func<T>>[] exprs)
where T:new()
{
var myType = me.GetType();
foreach(var expr in exprs)
{
var memberName = expr.GetName()
var myMember = myType.GetMember(memberName,
BindingFlags.Instance|BindingFlags.Public
|BindingFlags.NonPublic|BindingFlags.FlattenHierarchy,
MemberTypes.Field|MemberTypes.Property);
if(myMember == null)
throw new InvalidOperationException(
"Only property or field members are valid as expression parameters");
//it'd be nice to put these under some umbrella of "DataMembers",
//abstracting the GetValue/SetValue methods
if(myMember.MemberType == MemberTypes.Field)
((FieldInfo)myMember).SetValue(me, new T());
else
((PropertyInfo)myMember).SetValue(me, new T());
}
}
//usage
class MyClass
{
public List<double[][]> list1;
public List<double[][]> list2;
public MyOtherObject object1;
public MyClass()
{
this.Initialize(()=>list1,()=>list2);
this.Initialize(()=>object1); //each call can only have parameters of one type
}
}
Die Implikation ist hier offensichtlich; es ist mehr Ärger als es wert ist.
Um zu erklären, warum ich scheinbar gerade dieses herumliegen hatte; Obiges ist eine Adaption einer Methode, die ich verwende, um ArgumentNullExceptions basierend auf übergebenen Parametern zu werfen, die erfordert, dass die Werte in Expressions eingekapselt werden, um die Namen der tatsächlichen Parameter von der aufrufenden Methode beizubehalten. In dieser Situation ist die Komplexität hinter den Kulissen reduziert, da ich im Haupthelfer nur eine Null-Überprüfung benötige und die zusätzliche Komplexität spart mir viel mehr, als ich ausgeben kann, indem ich meine Null-Checks in jedem einzeilen lasse Methode und Konstruktor der Codebasis.
Ich empfehle ReSharper als eine langfristige Lösung zur Verringerung dieser Typisierung. Wenn der Typ eines Zuweisungsziels bekannt ist (wie z. B. für Felder und Eigenschaften) und Sie = new
eingeben, wird ReSharper einen Vorschlag für den Typ des Konstruktors anzeigen und ihn für Sie automatisch ausfüllen, wenn Sie möchten. Wenn Sie danach entweder den Typ oder den Konstruktor ändern, kennzeichnet R # die Zuweisung als inkonsistent und Sie können R # anweisen, den Wert zu ändern, der mit dem anderen übereinstimmen soll.
Verwenden Sie übrigens keine Arrays von Arrays. Erstellen Sie stattdessen ein geeignetes Datenmodell. –