Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/305.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C#中的代码简洁性—压缩一个setter,如果为null则抛出_C#_Getter Setter_Setter - Fatal编程技术网

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

C#中的代码简洁性—压缩一个setter,如果为null则抛出,c#,getter-setter,setter,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))

在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;
  }
}
对于更现代的实现,可以使用空合并运算符和表达式体将其压缩到一定量:

private Item _item;
public virtual Item Item {
  get => _item;
  set => _item = value ?? throw new ArgumentNullException(nameof(value));
}
然而,我很好奇,这是否能完全归结为标准参考的变化:

public virtual Item Item { get; set; }
这样您就不必定义私有项

建议?或者第二个代码块是否像我所能得到的那样高效/简单


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

免责声明:这些是将无效分配过滤到属性中的潜在“替代”方法。这可能无法直接回答这个问题,而是给出了如何在不定义私有属性和明确定义
getters
setters
的情况下更一般地进行操作的思路

根据
实际是什么,您可能可以通过将其创建为结构来创建
不可为空
类型

不可为空的类型被称为
structs
。它们不是什么新东西,它们是允许存储int、string、bool等类型属性的值类型

截至MSDN:

结构类型是通常用于封装的值类型 相关变量的小组,例如 矩形或库存中项目的特征

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

编辑(
Struct
如果
对象
应该是
不可为空的类型
,但是如果我们讨论的是类的属性,那么请阅读下文。):

另一种方法是使用
OnPropertyChanged
事件,它是
INotifyPropertyChanged
接口的一部分

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

void item_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
    var propertyValue = sender.GetType().GetProperty(e.PropertyName).GetValue(sender);
}
另一个解决方案是使用
DataAnnotations
并在属性上添加
Required
属性。如果我没有弄错的话,他们不会马上扔掉,除非你调用你自己的validate函数来验证这个类,我想,结合上面的方法,这会很好地工作,而且会很通用。一旦编写完成,您就不必显式地编写
getter
setter
,而是只将一个事件附加到类中,并在属性更改后验证它

下面是一个小例子:

例如,您的
项目
模型

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
   );
}
public bool TryValidate(object@object,out-ICollectionresults){
var context=new ValidationContext(@object,serviceProvider:null,items:null);
结果=新列表();
返回Validator.TryValidateObject(
@对象、上下文、结果、,
validateAllProperties:true
);
}
在该函数中,如果验证失败,您当然会抛出一个异常,
results
数组将包含它在默认消息中失败的属性(如果我没有弄错的话)。我认为这有点复杂,但如果您希望减少属性和
setter
实现的数量,这可能是一个进步。我不确定开销等。我个人认为,在更大范围内,这对于验证从db数据或任何外部源动态创建的模型非常有用


| | |

研究面向方面的编程,PostSharp。我实际上是在当前的C#框架内寻找解决方案,而不是我必须花钱的东西。现在,我的用例主张不支持付费产品。“C#中的代码简洁性”在您的问题中。我继续把你评论中的附加信息放在你的问题中,这会影响潜在答案的有效性。下次你可以自己点击,你也可能想读。也许只是我,但我一直认为标题是整个帖子的组成部分,也是问题本身的一部分。除非标题与内容真正隔离,并且与内容没有关系?从大量的位置来看,这将是一个严重的问题。例如,在structI中编辑get/set可能会更明确一些,但我的目的是使其尽可能通用,以避免其他问题纠缠在一起。这适用于使用域实体的简单MVC5、存储库模式、DDD。我不确定结构在这方面有什么帮助(以前从未使用过结构),因为我是根据代码优先原则“使用”数据库中的表和字段的。@RenéKåbis我不知道结构如何使它在您的情况下比标准类对象更通用,并停止您上面所说的任何事情。如果
不为null,则将其设置为不可为null的类型(struct)就足够了。如果您正在谈论
项中的特定属性
,请阅读我的编辑。
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
   );
}