在泛型中返回新实例而不是空实例

本文关键字:实例 泛型 返回 新实例 | 更新日期: 2023-09-27 18:02:22

我有一个从隔离存储中提取对象的类。如果它找不到有问题的对象,它返回default(T),它将为空,因为它们是引用类型。如果返回的值是null,我做一个简单的检查,并在调用者中分配一个新的实例,但我更愿意在存储逻辑中这样做。

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

在泛型中返回新实例而不是空实例

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

一样:

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

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

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的情况是一个特殊的情况,作为一个引用类型,它可以是null,并且没有一个公共的默认构造函数,这就是你在这里得到的而不是string . empty。nullable类型也给出null

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

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

您也可以调用Activator.CreateInstance<T>(),但如果该类型没有正确的构造函数,则会抛出。

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

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

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

这行得通:

使用系统;

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);
    }
}

从泛型方法实例化任何类型的变量(包括可空结构)?

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。