如何在C#中使用通用参数T Nullable?

时间:2016-10-04 13:27:40

标签: c# generics

我正在创建一个应该能够返回null的通用方法。

作为一个例子,我在下面创建了这个方法GetSecondSmallest(List<T>)。此函数循环遍历所有IComparable项,并在可能的情况下返回第二个最小项。如果此项目不存在,则返回null

public T? GetSecondSmallest<T>(List<T> items) where T : Nullable, IComparable
{
    if (items.Count == 0) return null;

    T smallest = items[0];
    T? secondSmallest = null;

    // Find second smallest by looping through list

    return secondSmallest;
}

此方法的两个示例用法是:

GetSecondSmallest(new List<int> {4, 2, 3, 1, 6, 8}) // Should return 2
GetSecondSmallest(new List<MyComparable> {new MyComparable('x')}) // Should return null

当您尝试编译此代码时,您将看到问题所在:

  

错误CS0717 'Nullable':静态类不能用作约束

如何让此方法返回Tnull的实例?

编辑:我已经看过this question,但这不回答我的问题,因为在我的情况下,参数也是通用的,应该是Nullable。所以提供的答案不适用。

3 个答案:

答案 0 :(得分:3)

您不能将T缩小为可以为空的对象。您必须制作两种方法,一种用于T,另一种用于T?

public T? GetSecondSmallestAsNullable<T>(List<T> items) where T : struct
{
    return null;
}

public T GetSecondSmallestAsClass<T>(List<T> items) where T : class
{
    return null;
}

答案 1 :(得分:1)

使用包装类(如Tuple)来包装结果值。在下面的示例中,如果没有第二个最小项,则返回null,否则返回具有第二个最小值的Tuple。

public static void Main()
{
    var result1 = GetSecondSmallest(new List<int>
    {
    4, 2, 3, 1, 6, 8
    }); // Should return 2

    var result2 = GetSecondSmallest(new List<MyComparable>
    {
    new MyComparable('x')
    }); // Should return null

    Console.WriteLine("result1=" + result1.Item1);
    Console.WriteLine("result2 == null: " + (result2 == null));
}

public static Tuple<T> GetSecondSmallest<T>(List<T> items)where T : IComparable
{
    return items.Skip(1).Select(v => Tuple.Create(v)).FirstOrDefault();
}

答案 2 :(得分:0)

将返回类型更改为Nullable,并使用非可空参数

调用该方法

简单示例:

static void Main(string[] args)
{
    int? i = GetValueOrNull<int>(null, string.Empty);
}


public static Nullable<T> GetValueOrNull<T>(DbDataRecord reader, string columnName) where T : struct
{
    object columnValue = reader[columnName];

    if (!(columnValue is DBNull))
        return (T)columnValue;

    return null;
}

Nullable type as a generic parameter possible?

<强> UPD

像这样:

public Nullable<T> GetSecondSmallest<T>(List<T> items) where T : IComparable
{
    if (items.Count == 0) return null;

    Nullable<T> smallest = items[0];
    Nullable<T> secondSmallest = null;

    // Find second smallest by looping through list

    return secondSmallest;
}