我有一个字符串属性具有最大长度要求,因为数据链接到数据库.如果调用者尝试设置超过此长度的字符串,我应该抛出什么异常?
例如,这个C#代码:
public string MyProperty
{
get
{
return _MyBackingField;
}
set
{
if (value.Length > 100)
throw new FooException("MyProperty has a maximum length of 100.");
_MyBackingField = value;
}
}
Run Code Online (Sandbox Code Playgroud)
我考虑过ArgumentException,但这似乎不对.从技术上讲,它是一个功能 - MyProperty_set(string value)- 所以ArgumentException可以制作一个案例,但它不是作为消费者眼睛的一个功能被调用 - 它位于赋值运算符的右侧.
这个问题也可能扩展到包括在属性设置器中完成的各种数据验证,但我对上述情况特别感兴趣.
在我的应用程序中,如果特定类的属性为null或为空(如果它是一个字符串),我需要抛出异常.我不确定在这种情况下使用的最佳例外是什么.我不想创建一个新的异常,我不确定ArgumentNullException在这种情况下是否合适.
我应该创建一个新的例外还是我可以使用的例外?
我不介意抛出一个ApplicationException.
我有一个由两个类继承的抽象类.这两个类都代表数据库中的表.虽然在抽象类中我遇到了映射表达式的麻烦,因此我不断得到它无法转换为SQL的异常.我在Stackoverflow中找到的所有问题都在谈论已经为我工作的列.
下面是一个非常简单的代码,显示了我的意思.汽车和摩托车有完全独立的_isNew Expression实现.
public abstract class Vehicle {
public abstract boolean IsNew;
}
public partial class Car: Vehicle {
public override boolean IsNew {
get { _isNew.Invoke(this); }
}
}
public partial class Motorcycle: Vehicle {
public override boolean IsNew {
get { _isNew.Invoke(this); }
}
}
Run Code Online (Sandbox Code Playgroud)
我希望能够在IQueryable上调用_isNew表达式或IsNew属性,但是如果Vehicle是Car类型,它会运行Car类的_isNew.无论如何我能做到吗?我尝试的所有解决方案都引发了一个异常,它无法转换为SQL.
所以我听说在这样的属性中验证一个值:
//dummy example, let's assume that I want my value without dots
public string MyProp
{
set
{
if(value.Contains('.'))
throw new ArgumentException("Must not contain '.'", "value");
}
}
Run Code Online (Sandbox Code Playgroud)
是错的,我应该避免它.
但在早些时候,我被告知这是好方法.我们可以使用封装,只有一个地方可以检查,DRY等.
我的小榜样出了什么问题?
对于问题的某些上下文 - 我使用延迟加载来推迟类中某些属性的完全初始化,直到需要它们时(如果有的话),因为它们的计算成本可能很高。
我的问题是 - 在 python 中,如果在计算属性值时发生错误,或者无法计算该值,那么引发异常是可以接受的还是客观上是一个坏主意?
我知道这个问题:最佳实践:从属性中抛出异常- 并且在回顾其中的要点后实际上重新措辞了这个问题。
然而,我真的在寻找有关 python 的明确答案。例如,getter 是否应该始终返回一个值,即使该值为 None?在其他语言中,例如 c#,对于如何设计属性有明确的建议。
避免从属性获取器抛出异常。
属性获取器应该是简单的操作,并且不应该有任何先决条件。如果 getter 可以抛出异常,那么它可能应该被重新设计为一个方法。请注意,此规则不适用于索引器,我们确实期望在验证参数时出现异常
http://msdn.microsoft.com/en-us/library/ms229006.aspx
在 python 中也是如此吗?这个属性真的应该是一个方法吗?我可以看到在强类型语言(例如 c#)中这可能是一个问题,但我不确定这里是否成立。在调试器中测试它按预期工作。
需要明确的是,我正在测试如下内容。
class A(object):
def __init__(self):
self.__x = None
@property
def x(self):
if not self.__x:
self.__x = calculate_x()
if not some_test(self.__x):
# Is this a bad idea?
raise ValueError('Get x error {}'.format(self.__x))
return self.__x
@x.setter
def x(self, value):
if not some_test(value):
raise ValueError('Set x error {}'.format(value))
self.__x = value
Run Code Online (Sandbox Code Playgroud)
我一直是 RTFM 并了解很多有关属性的知识,但似乎看不到任何使用它或警告它的东西。这一切是完全可以接受的还是我创造了某种来自地狱的可怕的反模式?
我尝试这样做的原因是因为我想到了类似“惰性”描述符的东西,它允许我快速标记属性。例如
from …Run Code Online (Sandbox Code Playgroud) 我总是听到那些说安装员和吸气者应该快速而不会抛出异常的人.
现在,如果是,如果没有抛出异常,我应该如何处理传递给setter的无效值?
c# ×6
exception ×3
.net ×2
properties ×2
.net-3.5 ×1
dry ×1
inheritance ×1
linq ×1
python ×1
validation ×1