C#中的代码简洁 - 压缩一个setter,如果为null则抛出

时间:2017-12-05 22:53:49

标签: c# getter-setter setter

在C#的早期版本中,如果您想阻止空引用异常,则需要以防御方式构建您的setter:

public Guid ItemId { get; set; } //foreign key, required

private Item _item;
public virtual Item Item {
  get {
    return _item;
  }
  set {
    if(value == null) throw new ArgumentNullException(nameof(value));
    _item = value;
    ItemId = value.ItemId;
  }
}

使用更现代的实现,可以使用null-coalescing运算符和表达式主体将其压缩一定量:

private Item _item;
public virtual Item Item {
  get => _item;
  set => _item = value ?? throw new ArgumentNullException(nameof(value));
}

但是,如果不能将其完全缩减为标准参考的变体,我很好奇:

public virtual Item Item { get; set; }

这样您就不必定义私人物品。

连连呢?或者第二个代码块是否有效/简单?

我正在寻找当前C#框架内的解决方案,而不是我必须花钱的东西。现在我的用例命题不支持付费产品

1 个答案:

答案 0 :(得分:1)

免责声明:这些是将无效分配过滤到属性的潜在“替代”方法。这可能无法直接回答问题,而是提出如何在不定义私有属性并明确定义getterssetters的情况下继续更多地进行操作的想法。

根据Item实际上是什么,您可以通过将其创建为结构来创建non-nullable类型的Item

非可空类型称为structs。它们并不新鲜,它们是允许存储int,string,bool等类型属性的值类型。

与MSDN一样:

  

结构类型是一种通常用于封装的值类型   小组相关变量,例如a的坐标   矩形或库存中物品的特征。

     

以下示例显示了一个简单的结构声明:

public struct Book  
{  
    public decimal price{ get; set;}
    public string title;  
    public string author;  
}  

Reference

如果Struct应该是object,那么编辑(non-nullable type就足够了,但是如果我们正在讨论该类的属性,请阅读以下内容。):

另一种方法是使用属于OnPropertyChanged接口的INotifyPropertyChanged事件。

虽然事件没有明确地为您提供已更改为的值,但您可以抓取它,因为它会为您提供属性名称。所以你可以运行你的验证帖子分配然后抛出,但我想它可能不是最好的选择。

void item_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
    var propertyValue = sender.GetType().GetProperty(e.PropertyName).GetValue(sender);
}

另一种解决方案是使用DataAnnotations并在您的媒体资源上添加Required属性。如果我没弄错的话,他们不会马上扔掉,直到你调用自己的验证函数来验证类,我想,结合上面的方法,这将很好用,并且非常通用。编写完成后,您不必明确地编写getterssetters,而只需将一个事件附加到您的班级,并在属性更改后对其进行验证。

这是一个小例子:

您的Item模型,例如......

public class Item
{
    [Required]
    public string Name { get; set; } 
}

然后,您将实现一个验证所有属性的通用函数。

public bool TryValidate(object @object, out ICollection < ValidationResult > results) {
   var context = new ValidationContext(@object, serviceProvider: null, items: null);

   results = new List <ValidationResult> ();

   return Validator.TryValidateObject(
    @object, context, results,
    validateAllProperties: true
   );
}

在该函数内部,如果验证失败,您当然会抛出异常,如果我没有弄错,您的results数组将包含在默认消息上失败的属性。我相信这有点复杂,但如果您正在寻求减少属性和setter实现的数量,这可能是向前迈出的一步。我不确定开销等。就个人而言,我认为在更大范围内,这对于验证从db数据或任何外部源动态创建的模型非常有用。

Validator Reference | Data Annotations Reference | ValidationResults Reference | PropertyChanged MSDN Sample