基于可空类型创建泛型类的实例

时间:2016-03-10 09:45:26

标签: c#

我想创建泛型函数,它将某些类型的值作为参数。

  • 此类型可以是否可为空。
  • 如果value为null,则函数应返回null。
  • 如果它不为空,并且它不是可空类型,则函数应该返回MyGenericClass<T>(parameter)(参数也可以通过属性设置,这里不需要使用构造函数)
  • 如果它不为空,并且它的可空类型而不是函数应返回类似MyGenericClass<NotNullType(T)>(parameter.Value) 示例的内容:对于参数int? x,函数应该返回MyGenericClass<int>(x.Value)

以下是我为编写此类操作而编写但未成功的代码:

private MyGenericClass GetMyGenericClassOrNull<T> (T value) {
    if (value != null) {
        var underlyingType = Nullable.GetUnderlyingType(typeof(T));
        if (underlyingType == null) {
            return new MyGenericClass<T>(value);
        } else {
            return new MyGenericClass<underlyingType>(value);
        }
    }
    return null;
}

正如您所期望的那样:return new MyGenericClass<underlyingType>(value);在这里存在问题。

有没有办法做这样的事情?

2 个答案:

答案 0 :(得分:2)

您可以尝试:

public class MyGenericClass
{
}

public class MyGenericClass<T> : MyGenericClass
{
    public MyGenericClass(T value)
    {
    }
}

public static MyGenericClass GetMyGenericClassOrNull<T>(T? value) where T : struct
{
    if (value != null)
    {
        return new MyGenericClass<T>(value.Value);
    }

    return null;
}

public static MyGenericClass GetMyGenericClassOrNull<T>(T value)
{
    if (value != null)
    {
        return new MyGenericClass<T>(value);
    }

    return null;
}

您有两种不同的方法。可以为Nullable的类型将转到第一个类型,其中T是不可为空的“基础”类型。

请注意,如果需要,您可以毫无问题地制作签名public static MyGenericClass<T>。目前尚不清楚MyGenericClass是如何构建的。

答案 1 :(得分:2)

您可以使用Type.MakeGenericType创建泛型类型的实例。

您的方法存在问题:MyGenericClass<int?>(例如)不是MyGenericClass<int>。不可能施放它们。输入中T的类型与其输出不同。我通过提供辅助类型参数来忽略该问题,该参数现在解决了问题。

private static MyGenericClass<T2> GetMyGenericClassOrNull<T, T2>(T value)
{
    if (value != null)
    {
        var underlyingType = Nullable.GetUnderlyingType(typeof(T));
        if (underlyingType == null)
        {
            return new MyGenericClass<T2>((T2)(object)value);
        }
        else
        {
            Type t = typeof(MyGenericClass<>).MakeGenericType(underlyingType);

            object o = Activator.CreateInstance(t, value);

            return (MyGenericClass<T2>)o;
        }
    }
    return null;
}

你可以像这样使用它:

var x = GetMyGenericClassOrNull<int?, int>(2);