首先让我解释一下我目前如何处理IPv4地址的验证:
public struct IPv4Address {
private string value;
private IPv4Address(string value) {
this.value = value;
}
private static IPv4Address CheckSyntax(string value) {
// If everything's fine...
return new IPv4Address(value);
// If something's wrong with the syntax...
throw new ApplicationException("message");
}
public static implicit operator IPv4Address(string value) {
return CheckSyntax(value);
}
public static implicit operator string(IPv4Address address) {
return address.value;
}
}
我有一堆像这样的结构。
他们经常有额外的私人成员来处理事情,但不公开公开方法。
以下是一个示例用法:
IPv4Address a;
IPv4Address b = "1.2.3.4";
a = b;
b = "5.6.7.8";
string address = a;
// c contains "1.2.3.4"
IPv4Address c = address;
// See if it's valid
try {
IPv4Address d = "111.222.333.444";
}
catch (ApplicationException e) {
// Handle the exception...
}
我可以感觉到有一些非常令人不安的事情,因此我正在考虑使用像IsIPv4Address等方法切换到静态类。
现在,我认为上述方法存在问题:
新的团队成员将不得不围绕这个
可能妨碍与第三方代码的集成
例外费用昂贵
从来没有见过这样的东西,我内心保守的是:)
然后我喜欢它:
因为你有价值类型所以非常接近拥有很多专门的原语。
在实践中,它们通常可以像原始类型一样使用,例如,将上面的结构传递给接受字符串的方法不是问题。
而且,我最喜欢的,你可以在对象之间传递这些结构,并确保它们包含语法上有效的值。这也避免了必须始终检查是否正确,如果不必要地进行甚至忘记,这可能是昂贵的。
我找不到上述方法的致命缺陷(这里只是初学者),您怎么看?
编辑:,因为您可以从第一行推断这只是一个示例,我不是要求验证IP地址的方法。
答案 0 :(得分:4)
我也非常喜欢在框架中模仿原始模式的概念,因此我会遵循这一概念并倾向于IpV4Address.Parse("1.2.3.4")
(以及TryParse
)而非隐式演员。
答案 1 :(得分:4)
首先,您应该阅读有关隐式转换的帖子,以及何时使用它(以及为什么在您的方案中使用它很糟糕),您可以启动here。
如果你需要有检查方法,它们应该是公共静态的,而不是这种奇怪的结构,除此之外,有这样的方法允许你选择是否要抛出异常(如.Parse()
方法),或者通过返回一些应该检查的值(如.TryParse()
方法)
除此之外,如果您真的想要,使用静态方法创建有效对象并不意味着您不能使用值类型(struct)而不是类。另外,请记住结构具有隐式空构造函数,您无法“隐藏”,因此即使您的构造也可以像这样使用:
IPv4Address a = new IPv4Address();
会给你无效的结构(值将为null)。
答案 2 :(得分:0)
似乎很多复杂而没有任何好处。只是因为你的意思并不代表你应该这样做。
而不是返回IP的CheckSyntax(字符串值)(这个方法措辞不好btw)我会有类似的东西
bool IsIP(string)
然后你可以将它放在实用程序类,基类或某个地方的单独抽象中。
答案 3 :(得分:0)
来自MSDN topic on implicit conversions
预定义的隐式转换 永远成功,永远不会 要抛出的异常。正确 设计用户定义的隐式 转换应该展示这些 特征
微软本身并不总是遵循这一建议。以下使用System.Xml.Linq.XName的隐式运算符会抛出XmlException:
XName xname = ":";
也许System.Xml.Linq
的设计师通过not documenting例外逃脱了它: - )