当不允许属性设置器时抛出什么异常?
我有一个具有虚拟属性的基类:
public virtual string Name { get; set; }
然后我有一个仅重写该属性的 getter 的派生类
public override string Name
{
get { return "Fixed Name"; }
}
问题是这只重写了 getter。如果有人调用 setter,基类 setter 将被调用,并且调用者不会知道它是无效的。
所以我想我会做类似的事情:
public override string Name
{
get { return "Fixed Name"; }
set { throw new Exception(); } //which exception type?
}
所以两个(相关问题):
- 有更好的模式供我使用吗?
- 如果我应该使用上面的模式,要使用什么例外?
编辑:为什么一种例外比另一种例外更受欢迎的一些原因是很好的。我和我的同事在 NotSupported
和 InvalidOperation
之间也有同样的争论。
I have a base class that has a virtual property:
public virtual string Name { get; set; }
then I have a derived class that overrides only the getter of the property
public override string Name
{
get { return "Fixed Name"; }
}
The problem is this only overrides the getter. If someone calls the setter the base class setter will get called, and the caller won't know that it's ineffective.
So I thought I'd do something like:
public override string Name
{
get { return "Fixed Name"; }
set { throw new Exception(); } //which exception type?
}
So two (related questions):
- Is there a better pattern for me to use?
- If I should be using the above pattern, what exception to use?
Edit: Some reasons why one exception would be preferred over another would be good. My co-worker and I have had the same argument between NotSupported
and InvalidOperation
.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
抛出 NotSupportedException 异常。
引用链接中的内容:
我的意见是 InvalidOperationException 不是正确的选项。
引用自MSDN:
您的情况与当前状态无关。就是类合约不支持操作。
Throw NotSupportedException exception.
Quote from the link:
My opinion is that InvalidOperationException is not a correct option.
Quote from MSDN:
There is nothing about current state in your situation. It is that the class contract does not support the operation.
它违反了里氏替换原则,这就是为什么它是个坏主意。
It breaks Liskov Substitution Principle and that's why it is bad idea.
如果可以的话,您可以尝试将 setter 移至基类的构造函数并将 setter 设为私有。或者正如 Jon 建议的那样,创建带有所有实现都支持的 getter 的抽象基类/接口。
这将避免抛出异常的整个情况。
If you can you could try to move setter to constructor of the base class and make setter private. Or as Jon suggested create abstract base class / interface with getters that are supported in all implementations.
This would avoid the whole situation with throwing exception.
如果基类实际上允许设置名称(而不是公开不能保证工作的抽象设置器),则派生类也应该这样做。如果您想要一个层次结构,其中包含一些可以设置名称的类和一些不能设置名称的类,则两种类都应该继承自具有非虚拟读写
的抽象
属性链接到抽象ReadableXX
类NameGetName
和SetName
方法。它还应该提供一些方法来指示是否支持SetName
(例如CanSetName
方法)。该类的只读变体可以定义一个“新”只读Name
属性,该属性将链接到GetName
,并具有其SetName
覆盖抛出NotSupportedException
。如果类的规范规定SetName
仅在CanSetName
返回 true 时才起作用,那么让SetName
在的类中抛出异常CanSetName
返回 false 不会违反里氏替换原则。If the base class actually allows setting the name (as opposed to exposing an abstract setter which isn't guaranteed to work), derived classes should do so as well. If you want a hierarchy which includes some classes where the name can be set and some where it cannot, both kinds of class should inherit from an abstract
ReadableXX
class with a non-virtual read-writeName
property that chains to abstractGetName
andSetName
methods. It should also provide some means of indicating whetherSetName
will be supported (e.g. aCanSetName
method). A read-only variant of the class could define a "new" read-onlyName
property that would chain toGetName
, and have itsSetName
override throwNotSupportedException
. If the specification for the class says thatSetName
will only work ifCanSetName
returns true, then havingSetName
throw an exception in classes whereCanSetName
returns false would not violate the Liskov Substitution Principle.在这里,我会选择 NotImplementedException。
Here I'd go for a NotImplementedException.