具有空访问器的属性

本文关键字:属性 访问 | 更新日期: 2023-09-27 18:20:22

虽然我当然熟悉自动属性,但我只是在工作中遇到了这个,它似乎是一个明显不同的野兽:

public SomeType SomeProp
{
  get
  {
    return someField;
  }
  set
  {
  }
}

我甚至对它的编译感到惊讶,我想这一定是一个错误:属性似乎允许设置,但这样做绝对没有任何作用。

这种结构有什么用吗?它是不是像电梯里的"关门"按钮一样什么都不做,但让用户感觉良好?

具有空访问器的属性

为什么不编译它?setter实际上只是一个带有单个参数的void方法。您可以非常容易地编写损坏的方法,而不必期望编译器注意到——属性也是如此。

然而,我很难想象在任何情况下,除了"部分"实现之外,这都是经过深思熟虑的——例如,为了演示语言功能,或者如果你正在测试确实设置了属性的东西,但你不在乎测试将其设置为什么

当结果需要在web服务中序列化或使用XML或二进制序列化程序时,您经常会看到这种情况。

这是懒惰和草率的,但它经常发生。这使对象具有属性可设置的"外观"。如果这样做是为了实现一个接口并允许编译,那么做这件事的开发人员就需要用一个钝的物体随意敲打他的头部和肩部,因为他刚刚破坏了接口。如果有正当理由不能实现它,那么开发人员需要把它交给架构师审查。在实现接口时,不能只留下空的存根方法。如果您目前还没有为实现定义技术,那么至少抛出一个新的NotImplementedException,这样单元测试就会捕捉到它

至于序列化:ReadOnly属性不会包含在常规序列化中,这可能会使web服务客户端无法使用该属性。(ref:Read Only Properties Cannot Be Exposed by XMLWeb Services。)这也是我们都应该转向WCF和DataContracts的原因之一。如果通过WCF接受此类作为方法的输入类型,则再次检索钝对象。

这本身似乎并不有用,但考虑一个需要类具有SomeProp的接口,您需要在类中实现该接口,但SomeProp只能读取,不能写入。

public interface IQuestion
{
    public int AnwserToLife { get; set; } //leave out 'set' for read-only
}
public class HitchHiker : IQuestion
{
    public int AnwserToLife
    {
        get
        {
            return 42;
        }
        set
        {  
            //never changes
        }
    }
}

有一些用例,这将是一个必要的解决方法,其中一些我已经"在野外"遇到过了。

例如:该属性是旧时代的遗迹,不再使用,但应用程序的其他部分从未更新(来源丢失?第三方?),并坚持设置该属性。我看到在旧代码中,需要插件在更新某些数据集后设置isDirty属性,当实现更改为在自己身上观察数据集时,isDirty特性变得无用,但无法收起,因为其他代码仍然想设置它。

我建议避免这种编程。它会编译,因为没有理由不编译,但如果接口要求您实现setter方法,那么有两个选项:

  1. setter是多余的,并且该属性应为只读,或者
  2. 你的代码中有一部分会设置这个值,并错误地认为它有效