كيف يمكنني إنشاء مثيل من نوع صفيف التعسفي في وقت التشغيل؟
-
03-07-2019 - |
سؤال
وأنا أحاول أن إلغاء تسلسل مجموعة من نوع غير معروف في وقت الترجمة. في وقت التشغيل لقد اكتشفت نوع، ولكن أنا لا أعرف كيف لإنشاء مثيل.
وشيء من هذا القبيل:
Object o = Activator.CreateInstance(type);
والذي لا يعمل لأنه لا يوجد منشئ parameterless، لا يبدو صفيف لديك أي المنشئ.
المحلول
استخدم Array.CreateInstance .
نصائح أخرى
ويمكنك استخدام واحدة من الزائدة CreateInstance صفيف ومنها مثلا: -.
object o = Array.CreateInstance(type, 10);
وبساطة وظيفة القديمة، ولكن بينما كان يجيب على سؤال جديد، على الرغم من نشر سبيل المثال ذات الصلة من خلق مجموعة ومتعددة الأبعاد.
وعلى افتراض نوع (elementType
) كما int
ومجموعة ثنائية الأبعاد على سبيل المثال.
var size = new[] { 2, 3 };
var arr = Array.CreateInstance(typeof(int), size);
وعندما حان ثنائية الأبعاد، على سبيل المثال، يمكن مأهولة
var value = 1;
for (int i = 0; i < size[0]; i++)
for (int j = 0; j < size[1]; j++)
arr.SetValue(value++, new[] { i, j });
//arr = [ [ 1, 2, 3 ], [ 4, 5, 6 ] ]
وبديل ذلك هو استخدام أشجار التعبير عن الأداء. على سبيل المثال؛ إذا كان لديك مجموعة <م> نوع م>، type
يمكن أن تفعله
var ctor = type.GetConstructors().First(); // or find suitable constructor
var argsExpr = ctor.GetParameters().Select(x => Expression.Constant(0));
var func = Expression.Lambda<Func<object>>(Expression.New(ctor, argsExpr)).Compile();
وهذا يعود مجرد مجموعة فارغة. ربما ليس من المفيد جدا. الدول MSDN GetConstructors
لا يضمن أي أمر، لذلك قد تحتاج إلى المنطق للعثور على منشئ الصحيح مع المعلمات الصحيحة لمثيل مع الحجم الصحيح. على سبيل المثال؛ هل يمكن أن تفعل:
static Func<object> ArrayCreateInstance(Type type, params int[] bounds) // can be generic too
{
var ctor = type
.GetConstructors()
.OrderBy(x => x.GetParameters().Length) // find constructor with least parameters
.First();
var argsExpr = bounds.Select(x => Expression.Constant(x)); // set size
return Expression.Lambda<Func<object>>(Expression.New(ctor, argsExpr)).Compile();
}
والشيء نفسه يمكن تحقيقه أسهل بكثير مع Expression.NewArrayBounds
بدلا من Expression.New
، على مدى أكثر أنه يعمل إذا كان كل ما حصل هو مجموعة نوع العنصر، وليس نوع مصفوفة نفسها. عرض:
static Func<object> ArrayCreateInstance(Type type, params int[] bounds) // can be generic too
{
var argsExpr = bounds.Select(x => Expression.Constant(x)); // set size
var newExpr = Expression.NewArrayBounds(type.GetElementType(), argsExpr);
return Expression.Lambda<Func<object>>(newExpr).Compile();
}
// this exercise is pointless if you dont save the compiled delegate, but for demo purpose:
x = string[] {...
y = ArrayCreateInstance(x.GetType(), 10)(); // you get 1-d array with size 10
x = string[,,] {...
y = ArrayCreateInstance(x.GetType(), 10, 2, 3)(); // you get 3-d array like string[10, 2, 3]
x = string[][] {...
y = ArrayCreateInstance(x.GetType(), 10)(); // you get jagged array like string[10][]
ومجرد تغيير type.GetElementType()
إلى type
ببساطة إذا كنت تمر هو نوع العنصر نفسه.