【问题标题】:Return a new instance rather than a null instance in generics在泛型中返回一个新实例而不是一个空实例
【发布时间】:2011-07-16 13:00:09
【问题描述】:

我有一个从独立存储中提取对象的类。如果它找不到有问题的对象,它会返回 default(T),因为它们是引用类型,所以它会为 null。如果返回的值为 null,我会进行简单检查并在调用者中分配一个新实例,但我更愿意在存储逻辑中执行此操作。

所以我的问题是,有没有办法返回一个新的 T 对象有一个默认的空白构造函数?

【问题讨论】:

标签: c# generics windows-phone-7 isolatedstorage


【解决方案1】:

一个选项是使用约束“new”: http://msdn.microsoft.com/en-us/library/sd2w2ew5(v=vs.80).aspx

像这样:

public T GetNewItem()
    where T: new()
{
    return new T();
}

但是有这个约束意味着你不能使用没有默认构造函数的类型。所以你可以考虑使用 System.Activator.CreateInstance,但记住它可能会抛出异常:

T createInstance<T>()
{
    try
    {
        return System.Activator.CreateInstance<T>();
    }
    catch (MissingMethodException exc)
    {
        return default(T);
    }
}

因此,在初始化的早期就知道给定类型是否支持这一点可能是个好主意,这样做的方法如下:

T createInstance<T>()
{
    System.Reflection.ConstructorInfo constructor = (typeof(T)).GetConstructor(System.Type.EmptyTypes);
    if (ReferenceEquals(constructor, null))
    {
        //there is no default constructor
        return default(T);
    }
    else
    {
        //there is a default constructor
        //you can invoke it like so:
        return (T)constructor.Invoke(new object[0]);
        //return constructor.Invoke(new object[0]) as T; //If T is class
    }
}

当你在做的时候,为什么不让一个委托来创建一个实例呢?

Func<T> getConstructor<T>()
{
    System.Reflection.ConstructorInfo constructor = (typeof(T)).GetConstructor(System.Type.EmptyTypes);
    if (ReferenceEquals(constructor, null))
    {
        return () => { return default(T); };
    }
    else
    {
        return () => { return (T)constructor.Invoke(new object[0]); };
    }
}

一个如何使用它的例子(用LinqPad编译):

void Main()
{
    Console.WriteLine(getConstructor<object>()());
    Console.WriteLine(getConstructor<int>()());
    Console.WriteLine(getConstructor<string>()());
    Console.WriteLine(getConstructor<decimal>()());
    Console.WriteLine(getConstructor<DateTime>()());
    Console.WriteLine(getConstructor<int?>()());
}

输出是:

System.Object
0
null
0
01/01/0001 12:00:00 a.m.
null

字符串的情况是一种特殊情况,作为一个引用类型,它可以为空,并且没有你在这里得到的公共默认构造函数,而不是 String.Empty。可空类型也给出空值。

【讨论】:

    【解决方案2】:

    你可以为你的类型参数添加一个约束,但这会阻止任何支持空参数构造函数的类被用作类型参数。

    public class Foo<T> where T : new()
    {
        // Now you can say T blah = new T();
    }
    

    您也可以调用Activator.CreateInstance&lt;T&gt;(),但如果类型没有正确的构造函数,则会抛出异常。

    如果找不到对象,我认为您最好记录下您的方法返回null,并让调用代码在它认为合适的情况下处理该条件。它将处于知道如何进行的最佳位置。

    【讨论】:

      【解决方案3】:

      new() 约束添加到您的泛型方法中:

      public T Create<T>() where T: class, new()
      {
        return new T();
      }
      

      【讨论】:

        【解决方案4】:

        这行得通:

        使用系统;

        public class Test
        {
            static T CreateT<T>(bool _new) where T: new()
            {
                if (_new) return new T(); else return default(T);
            }
            public static void Main()
            {
                var o = CreateT<object>(true);
            }
        }
        

        【讨论】:

          【解决方案5】:

          来自Generic method to instantiate a variable of any type (including nullable struct)?

          public static T GetEmpty<T>() where T : new() //this constraint is important
          {
              return (T)Activator.CreateInstance(Nullable.GetUnderlyingType(typeof(T)) ?? typeof(T));
          }
          

          这也适用于可为空的结构。对于int?,它返回 0 而不是 null。更快接近here.

          【讨论】:

            猜你喜欢
            • 2016-01-21
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2023-03-08
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2013-02-18
            相关资源
            最近更新 更多