【问题标题】:C#: Strongly type heterogenous container accept nullable [duplicate]C#:强类型异构容器接受可为空的[重复]
【发布时间】:2021-10-31 03:23:48
【问题描述】:

我正在尝试将以下代码调整为可接受的可为空类型。考虑一下:

public sealed class JsonDictionary
{
    private readonly IDictionary<string, object> _data;

    public static readonly Key<int> Foo = new Key<int> { Name = "FOO" };
    public static readonly Key<double> Bar = new Key<double> { Name = "BAR" };
    public static readonly Key<List<double>> Vec = new Key<List<double>> { Name = "VEC" };

    public JsonDictionary()
    {
        _data = new Dictionary<string, object>();
    }

    public void Set<T>(Key<T> key, T obj)
    {
        _data[key.Name] = obj;
    }    
    public T Get<T>(Key<T> key)
    {
        return (T)_data[key.Name];
    }
    public class Key<T>
    {
        public string Name { get; init; }
    }
}

这很好用:

var d = new JsonDictionary();
d.Set(JsonDictionary.Foo, 42);
d.Set(JsonDictionary.Bar, 3.14);
d.Set(JsonDictionary.Vec, new List<double> { 1.0, 2.0, 3.0 });
Assert.Equal(42, d.Get(JsonDictionary.Foo));
Assert.Equal(3.14, d.Get(JsonDictionary.Bar));
Assert.Equal(new List<double> { 1.0, 2.0, 3.0 }, d.Get(JsonDictionary.Vec));

如何将 Set/Get API 更改为也接受可为空的类型?例如:

d.Set(JsonDictionary.Foo, null);
d.Set(JsonDictionary.Bar, null);
d.Set(JsonDictionary.Vec, null);

以下天真的尝试对我不起作用:

public void Set<T>(Key<T> key, T? obj)
{
    _data[key.Name] = obj;
}

更改基本类型,如下所示:

public static readonly Key<int?> Foo = new Key<int?> { Name = "FOO" };
public static readonly Key<double?> Bar = new Key<double?> { Name = "BAR" };
public static readonly Key<List<double>?> Vec = new Key<List<double>?> { Name = "VEC" };

确实可以按预期工作,但需要更多输入...直接在Set 函数中的任何其他解决方案(带有一些约束魔法)?


另一种解决方案可能是像这样复制代码:

public void Set<T>(Key<T> key, T? obj) where T : struct
{
    _data[key.Name] = obj;
}
public void Set<T>(Key<T> key, T? obj) where T : class
{
    _data[key.Name] = obj;
}

这也是我不想做的事情。我是否遗漏了这种强类型结构中的一些基本内容?

【问题讨论】:

  • 我不知道我这里有没有正确答案,这是一个猜测:。改变基本类型?喜欢:Key&lt;int?&gt;
  • 在我看来,最好的解决方案是@devlincarnate 给出的解决方案,在此过程中保持相同的基本类型更好。您在 Keys 中指定类型并同时尝试修改它。

标签: c# generics


【解决方案1】:

您所说的将基本数据类型更改为可空类型的解决方案似乎是唯一的选择。如果您尝试将 null 传递给不可为空的数据类型,例如 int,您将在运行时收到一个错误(您的编译器应该警告您)。 泛型只能执行它所传递的数据类型的功能!


// will receive an error here v
// passing a null into int
Set(new Key<int> { Name = "FOO" }, null);
public void Set(Key<int> key, int obj)
{
    _data[key.Name] = obj;
}

这基本上是您的代码试图做的事情,我可以看到它解决的唯一方法是:

  1. 修复数据类型

    Set<int?>(new Key<int?> { Name = "FOO" }, null);
    public void Set<T>(Key<T> key, T obj)
    {
        // Has no issue as you are setting a null to a nullable datatype
        _data[key.Name] = obj;
    }
    
  2. 丢弃空值或为空值保留值

    Set<T>(new Key<int> { Name = "FOO" }, null);
    public void Set<T>(Key<T> key, object obj)
    {
        // check if obj is the same type as T if not sets the name to -1 in the key's type
        // be care full though if you try to pass an int into a float you will also get -1
        _data[key.Name] = (obj is T ? obj : (T)-1);
    }
    

祝你好运,很抱歉我帮不上什么忙

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-01-29
    • 1970-01-01
    • 1970-01-01
    • 2011-11-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多