C# 8 - 在泛型中使用类型的可空和不可空版本

问题描述 投票:0回答:1

我需要在同一个泛型中使用两个版本的基类型:可为空和不可为空。 像整数?和 int,Guid?和GuidOnly?和 DateOnly 等等。 可空类型应该位于类属性中,不可空类型应该位于类字典的键中。并且应该使用 nullable 来搜索该字典。

示例:

var t = new GenericTest<int?, int> # ERROR: The type 'int?' must be convertible to 'int' in order to use it as parameter 'TK' in the generic class 'GenericTest<TK,TV>'
{
    Key = null
};
t.Values.Add(1, 2);

Console.WriteLine(t.FindValue());

class GenericTest<TK, TV> 
    where TK: TV
    where TV : notnull
{
    public TK? Key { get; set; }
    
    public Dictionary<TV, int> Values { get; set; } = new();

    public int FindValue()
    {
        if (Key == null)
            return 0;
        
        return Values.GetValueOrDefault(Key, 0);
    }
}

我也尝试仅使用 1 个通用参数,但收到警告

var t = new GenericTest<int?>
{
    Key = null
};
t.Values.Add(1, 3);

Console.WriteLine(t.FindValue());

class GenericTest<TK>
{
    public TK? Key { get; set; }
    
    public Dictionary<TK, int> Values { get; set; } = new(); # WARNING: Nullability of type argument 'TK' must match 'notnull' constraint in order to use it as parameter 'TKey'

    public int FindValue()
    {
        if (Key == null)
            return 0;
        
        return Values.GetValueOrDefault(Key, 0);
    }
}

好的,我正在添加约束,但又收到另一个警告:

var t = new GenericTest<int?> # WARNING: Nullability of type argument 'int?' must match 'notnull' constraint in order to use it as parameter 'TK'
{
    Key = null
};
t.Values.Add(1, 3);

Console.WriteLine(t.FindValue());

class GenericTest<TK> where TK : notnull # ADDED HERE
{
    public TK? Key { get; set; }
    
    public Dictionary<TK, int> Values { get; set; } = new();

    public int FindValue()
    {
        if (Key == null)
            return 0;
        
        return Values.GetValueOrDefault(Key, 0);
    }
}

是否可以在没有错误和警告的情况下实现这一目标?

c# .net generics nullable boxing
1个回答
1
投票

我不完全确定这是否是您想要的,但是:如果您想始终使用类型

T?
作为键,使用
T
作为值,您可以避免指定两个类型参数,例如所以:

class GenericTest<TK> where TK: struct
{
    public TK? Key { get; init; }

    public Dictionary<TK?, TK> Values { get; set; } = new();                     

    public TK FindValue()
    {
        if (Key == null)
            return default;

        return Values.GetValueOrDefault(Key, default);
    }
}

这适用于任何结构类型,当然包括

int
Guid
DateOnly

您的示例将看起来更像这样:

static void Main()
{
    var t = new GenericTest<int>
    {
        Key = 1
    };
    t.Values.Add(1, 2);

    Console.WriteLine(t.FindValue());
}
© www.soinside.com 2019 - 2024. All rights reserved.