具有空访问器的属性

3

虽然我当然熟悉自动属性,但我在工作中遇到了这个问题,它似乎是一个完全不同的东西:

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

我很惊讶它甚至编译通过了,我想这一定是一个bug: 这个属性似乎允许设置,但实际上根本不起作用。
这种构造有用吗?就像电梯里那些没有作用但能让用户感到好的“关门”按钮一样吗?

我猜因为这些类型的“特性”,C# 是这里最受欢迎的标签... =) - gdoron
@gdoron:这是一个非常方便的功能,可以替换像在C++或Java中需要实现的显式的“get/set”方法。这就像询问为什么一个空的“setSomeProp(SomeType s)”方法会编译一样。 - vgru
5个回答

5
为什么你认为它不会编译?setter只是一个带有单个参数的void方法,实际上。你可以很容易地编写错误的方法,而不指望编译器注意到——属性也是如此。
然而,我很难想象任何情况下这都是故意的,除了“部分”实现——例如展示语言特性,或者如果你正在测试某些设置属性的东西,但你不在乎测试将其设置为什么。(我个人通常至少记录一下已经设置属性。)

4

当需要通过web服务或使用XML或二进制序列化程序来序列化结果时,通常会出现这种情况。

这种做法是懒惰和粗心的,但它经常发生。这会使对象“看起来”具有可设置的属性。如果这样做是为了实现接口并允许编译,则执行此操作的开发人员应该受到惩罚,因为他刚刚破坏了接口。如果有有效的理由不能实现它,则开发人员需要将其退回给架构师进行审查。在实现接口时不应该只留下空的存根方法。如果目前没有定义实施技术,则至少抛出一个new NotImplementedException,以便单元测试能够捕获它。

就序列化而言:只读属性不包含在常规序列化中,这可能导致Web服务客户端无法使用属性。(参考:只读属性无法由XML Web服务公开。)这是我们所有人都应该转向WCF和DataContract的原因之一。如果您通过WCF将此类接受为方法的输入类型,那么再次召回钝物。


2

这个本身似乎没有什么用处,但考虑一个接口需要类具有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
        }
    }
}

所以你应该在C# 4.0中使用“适配器设计模式”或动态。 - gdoron
@parapura:我还没有遇到过这种情况的用例。让调用者认为他们已经设置了一个值,但实际上什么也没做,这是相当隐秘的。 - vgru
1
我不明白为什么你要故意以这种方式误导代码的用户。如果你不打算实现接口的一部分,至少应该使用 throw new NotImplementedException("explanation"); - Ade Stringer

1

有一些用例需要这种必要的解决方法,其中有些我已经在实际中遇到过。

例如:该属性是旧时代的遗留物,不再有用,但应用程序的某个其他部分从未更新(源代码丢失?第三方?),并坚持设置该属性。我曾在旧代码中看到过,需要插件在更新某些数据集后设置isDirty属性,当实现更改为观察数据集本身时,isDirty属性变得无用,但无法放弃,因为其他代码仍然希望设置它。


1
我建议避免这种编程方式。它可以编译通过,因为没有理由不行,但如果接口要求你实现一个setter方法,那么有两个选择:
  1. 要么这个setter是多余的,属性应该被设置为只读,或者
  2. 存在于你的代码中的某个部分将设置这个值并错误地假设它已经成功了。

在编程中,误导其他程序员是不可取的。如果在实际开发中遇到这种情况,应该找出问题所在并加以修复。如果可能的话,还应该与架构师和之前的开发人员进行深入讨论。 - EoRaptor013

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接