C# - 如何检查是否需要构造某种类型的对象?

时间:2013-08-01 06:58:00

标签: c# arrays object reflection

(我很抱歉,如果重复,我不确定是否要检查可空或原始或其他什么)

我正在创建变量Type的对象数组。它可以是intstringPointMyCustomClass(可能没有枚举,但它们与int相同吗?)。

<小时/> 输入:数组元素的类型。

黑匣子:检查是否构建了 NEEDS 类型。创建数组,如果需要contruction创建每个元素(使用默认值,因为它们此时无关紧要)。构造函数必须是无参数的( - >失败函数),但将字符串视为特殊类型。

输出 object(运行时类型为int[]string[]Point[]等。)

<小时/> 我面临的问题是我创建了一个充满null的数组。原语和结构很好,我得到int[]没有问题,但类导致“null[]”。
到目前为止我所拥有的(不确定我是否抓住了所有内容):

public object createArray(Type arrayElementType, int arrayLength)
{
    Array a = Array.CreateInstance(arrayElementType, arrayLength);
    if (!arrayElementType.IsPrimitive) // correct would be: if (!arrayElementType.IsValueType)
        for (int j = 0; j < arrayLength; j++)
            a.SetValue(Activator.CreateInstance(arrayElementType), j);
    return a;
}

2 个答案:

答案 0 :(得分:2)

这里的难点在于创建实例;很容易找出是否将在数组分配上创建实例:只需检查默认(T)值。但是我们如何手动创建实例?如果你的班级有五个构造函数怎么办? 在下面的代码中,我创建了一个实例,如果它的类有一个默认构造函数,它是 public 并且没有参数

public static T[] CreateArray<T>(int size) {
  if (size < 0)
    throw new ArgumentOutOfRangeException("size");

  T[] result = new T[size];

  // You may put any special cases here, e.g. if you want empty strings instead of nulls
  // uncomment the exerp:
  //if (typeof(T) == typeof(String)) {
  //  for (int i = 0; i < result.Length; ++i)
  //    result[i] = (T) ((Object) "");
  //   
  //  return result;  
  //}

  // If default value is null, instances should be created 
  // (if we manage to find out how to do it)
  if (Object.ReferenceEquals(null, default(T))) {
    // Do we have a constructor by default (public one and without parameters)?
    ConstructorInfo ci = typeof(T).GetConstructor(new Type[] { });

    // If do, let's create instances
    if (!Object.ReferenceEquals(null, ci))
      for (int i = 0; i < result.Length; ++i)
        result[i] = (T) (ci.Invoke(new Object[] { }));
  }

  return result;
}

测试用例:

  // int is a structore, its default value is 0, so i = [0, 0, 0, 0, 0]
  int[] i = CreateArray<int>(5);

  // String has no String() constructor, so s[] = [null, null, null, null, null]
  String[] s = CreateArray<String>(5); 

  // Button has Button() constructor, so b[] contains buttons 
  Button[] b = CreateArray<Button>(5);

答案 1 :(得分:2)

您可以尝试以下代码

public class TypeClass
{
    public static T[] CreateArray<T>(int arrayLength) // using T[] would save you from type-casting
        where T : new()     // <-- Constrain to types with a default constructor
    {
        T[] t = new T[arrayLength];
        for (int j = 0; j < arrayLength; j++)
            t[j] = new T();
        return t;
    }
}

public class MyClass
{
    static void Main(string[] args)
    {
        int [] intArray = TypeClass.CreateArray<int>(5);
        string [] stringArray = TypeClass.CreateArray<string>(5);
        Point [] pointArray = TypeClass.CreateArray<Point>(5);
        MyCustomClass [] myCustomClassArray = TypeClass.CreateArray<MyCustomClass>(5);
    }
}

这适用于已定义Primitive构造函数的所有classdefault类型。