【问题标题】:When new-able use new T(), otherwise use default(T)当 new-able 使用 new T(),否则使用 default(T)
【发布时间】:2014-10-01 13:52:46
【问题描述】:

我正在开发一个 C# 泛型函数。出错时,如果泛型可以new-able,返回new T(),否则返回default(T)

如下代码:

private T Func<T>()
{
    try
    {
        // try to do something...
    }
    catch (Exception exception)
    {
        if (T is new-able) // <---------- How to do this?
        {
            return new T();
        }
        else
        {
            return default(T);
        }
    }
}

我知道使用new T() 的用户需要where T : new()。这个问题是,如何在运行时判断这个?

【问题讨论】:

  • 虽然使用反射可以实现,但这表明该方法的调用者恕我直言,这是一个相当臭的约定。你能更好地描述一下你想要做什么吗?
  • 除非我弄错了,否则你不能只使用return Activator.CreateInstance(T)吗?
  • @Sayse 不,如果没有定义无参数构造函数,则会抛出异常。
  • @SriramSakthivel - 从 OP 的例子来看,我认为这会很好,但是谢谢
  • 这似乎是一个非常糟糕的设计。即使这样,您的代码似乎也没有实现您的设计目标:您似乎绝对不想让任何抛出的异常在您的函数之外可见。但是如果new T() 抛出怎么办?

标签: c# generics types default


【解决方案1】:

您只需要检查该类型是否具有无参数构造函数。您可以通过调用Type.GetConstructor 方法以空类型作为参数来实现。

var constructorInfo = typeof(T).GetConstructor(Type.EmptyTypes);
if(constructorInfo != null)
{
   //here you go
   object instance = constructorInfo.Invoke(null);
}

【讨论】:

  • 谢谢!在 here you go 部分,我如何将constructorInfo 用于新实例?
  • @LiJunLe 更新了我的答案,你得打电话给constructorInfo.Invoke
  • 回滚编辑:GetConstructor 如果您不指定BindingFlags.NonPublic,则方法仅返回公共构造函数;所以检查constructorInfo.IsPublic 是多余的。
【解决方案2】:

如果我没记错的话,如果T 是一个类,Activator.CreateInstance&lt;T&gt; 将返回一个使用无参数构造函数构造的对象,如果T 是一个结构体,则返回一个default(T)

您可以使用 Sriram 回答中的技术首先确保 T 存在无参数构造函数。

【讨论】:

  • 如果没有无参构造函数,会抛出异常。不是吗?
  • 在这种情况下,您仍然可以捕获异常并返回默认值(T)...性能不理想,但其他方面都可以。
  • @BatteryBackupUnit - 应该有异常来捕获异常,而不是程序流
  • @Sayse 我大体上同意,但不一定适用于这个具体的例子。我认为在你的团队/公司中定义这样的规则是可以的,但是假设这是一个“硬规则”而不详细解释它基本上是回归到一种自启蒙时代以来有点过时的(一种狂热的)行为。至于手头的话题stackoverflow.com/questions/729379/…包含了相当多的信息。
【解决方案3】:

您可以检查默认构造函数,如果找到,则执行 new T()。 为此,您可以使用以下内容:

var constructor = typeof(T).GetConstructor(Type.EmptyTypes);
if(constructor != null)
{
    return (T)constructor.Invoke(null);
}
else
{
    return default(T);
}

【讨论】:

  • new T(); 不会编译。因为没有定义new() 约束。
  • 哦,是的……你说得对。没有意识到这一点。如果约束到位,则无需检查默认构造函数
  • 感谢您的建议,但我不能在这里使用new T()。因为那必须声明我应该避免的where T : new()
  • 我已经根据@SriramSakthivel 更新了我的答案
【解决方案4】:

我很少玩MarcoLaser 的回答并做出了我的 '如果 T 是 newable 则获取实例构造函数'

public class MyClass<T>
{
        public MyClass()
        {
            var constructor = typeof(T).GetConstructor(Type.EmptyTypes);
            if (constructor != null)
                Data = (T)constructor.Invoke(null);  
        }

        public T Data { get; set; }
}



  

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-07-21
    相关资源
    最近更新 更多