【问题标题】:C# - How to check if object of a type needs to be constructed?C# - 如何检查是否需要构造一个类型的对象?
【发布时间】:2013-08-01 06:58:00
【问题描述】:

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

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


输入: 数组元素的类型。

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

输出: 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;
}

【问题讨论】:

  • 目前还不清楚您要达到的目标。让我们以string 为例 - 您显然想要一个非空字符串引用数组,但这些字符串的内容应该是什么?
  • @JonSkeet 内容无关紧要。它们不能为空。
  • 你能展示一些关于这个的代码吗?
  • 如果您告诉我们您打算如何使用这个数组,我们可能会提供更好的建议。目前,这感觉像是XY problem
  • @mini-me - 虽然人们继续尝试做奇怪或离奇的事情而没有提供背景,但总是值得让他们停下来,退后一步,画一个更大的图景,然后最终可能不会为可能会被更简单地解决的问题建立一个 Rube-Goldberg 解决方案。

标签: c# arrays object reflection


【解决方案1】:

这里的困难在于创建实例;很容易找出是否会在数组分配时创建实例:只需检查 default(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);

【讨论】:

    【解决方案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);
        }
    }
    

    这适用于定义了default 构造函数的所有Primitiveclass 类型。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-09-29
      • 2023-01-13
      • 1970-01-01
      • 2018-08-17
      • 2013-07-29
      • 2020-02-24
      • 1970-01-01
      • 2017-01-13
      相关资源
      最近更新 更多