【问题标题】:Generic throw function for non-nullable types非可空类型的通用 throw 函数
【发布时间】:2020-02-19 08:42:53
【问题描述】:

我正在尝试使用non-nullable properties during initialization 将现有项目转换为使用可为空的引用类型属性。

我正在使用这种方法来获取应该存在的属性:

public class Dog
{
    private Person? _person;
    public int Id { get; set; }

    public string Name { get; set; }

    public Person Person
    {
        get => _person ?? throw new InvalidOperationException(
            $"Unset property {nameof(_person)}. You probably forgot to Include it");
        set => _person = value;
    }
}

但是为几乎每个属性都写这个很乏味,所以我尝试制作一个通用的ThrowOrGet() 函数:

public static class Util
{
    public static T ThrowOrGet<T>([AllowNull] T obj)
    {
        if (obj == null)
        {
            throw new InvalidOperationException(
                $"Unset property {nameof(obj)}. You probably forgot to Include it");
        }
        return obj;
    }
}

这样使用:

public class Dog
{
    private Person? _person;
    public int Id { get; set; }

    public string Name { get; set; }

    public Person Person
    {
        get =>  Util.ThrowOrGet(_person); ---> "Possible null reference return"
        set => _person = value;
    }
}

但是函数Util.ThrowOrGet(_person); 现在说它是一个可能的null 引用返回。如果我内联该函数,它会按预期工作。 有没有办法制作一个通用函数来做到这一点?

【问题讨论】:

  • 这可能没有回答你的问题,但the way you test for null is wrong. 整个事情可以这样写:return person ?? throw new .... 就像你在你的财产中所做的那样。另外,getters should probably not throw exceptions——但如果你决定这样做——我会称之为TryGet,而不是ThrowOrGet。这里的 throw 并不是你想让你的方法做的主要事情——这是最后的手段。
  • 另外,你的nameof(obj),只会产生“obj”,这不是你用nameof(_person)内联它时得到的。

标签: c# c#-8.0 nullable-reference-types


【解决方案1】:

如果你只打算在引用类型上使用ThrowOrGet(你应该这样做,因为它对值类型没有意义),那么你应该像这样声明它:

public static T ThrowOrGet<T>(T? obj) where T : class
{
    if (obj == null)
    {
        throw new InvalidOperationException(
            $"Unset property {nameof(obj)}. You probably forgot to Include it");
    }
    return obj;
}

这表示该函数接受一个可以为空的参数,并且总是返回一个不可为空的引用。遵循这种模式比依赖属性更好,因为它们实际上只适用于复杂的情况,而事实并非如此。

【讨论】:

  • 这是正确的,但正如@haim770 对我的问题的评论所指出的那样; nameof(obj),只会产生“obj”,所以你不会知道缺少哪个类型
  • 这也是一个好点,您现在需要将它作为参数传递。
猜你喜欢
  • 1970-01-01
  • 2019-06-02
  • 1970-01-01
  • 1970-01-01
  • 2014-02-04
  • 1970-01-01
  • 1970-01-01
  • 2013-08-13
  • 1970-01-01
相关资源
最近更新 更多