在我的系统经常与机场代码(操作"YYZ"
,"LAX"
,"SFO"
等),他们总是在完全一样的格式(3封信,表示为大写)。系统通常每个API请求处理这些代码中的25-50个(不同),总共分配了上千个代码,它们在我们应用程序的许多层中传递,并且经常比较它们的相等性。
我们从传递字符串开始就可以了,但仍然可以正常工作,但很快就发现了很多编程错误,因为在期望3位代码的地方传递了错误的代码。我们还遇到了一些问题,我们应该进行不区分大小写的比较,而没有这样做,从而导致错误。
由此,我决定停止传递字符串并创建一个Airport
类,该类具有一个采用并验证机场代码的构造函数。
public sealed class Airport
{
public Airport(string code)
{
if (code == null)
{
throw new ArgumentNullException(nameof(code));
}
if (code.Length != 3 || !char.IsLetter(code[0])
|| !char.IsLetter(code[1]) || !char.IsLetter(code[2]))
{
throw new ArgumentException(
"Must be a 3 letter airport code.",
nameof(code));
}
Code = code.ToUpperInvariant();
}
public string Code { get; }
public override string ToString()
{
return Code;
}
private bool Equals(Airport other)
{
return string.Equals(Code, other.Code);
}
public override bool Equals(object obj)
{
return obj is Airport airport && Equals(airport);
}
public override int GetHashCode()
{
return Code?.GetHashCode() ?? 0;
}
public static bool operator ==(Airport left, Airport right)
{
return Equals(left, right);
}
public static bool operator !=(Airport left, Airport right)
{
return !Equals(left, right);
}
}
这使我们的代码更易于理解,并且简化了相等性检查,字典/集合用法。现在我们知道,如果我们的方法接受一个Airport
实例,它将按照我们期望的方式运行,那么它将方法检查简化为空引用检查。
但是,我确实注意到的是,垃圾收集运行的频率更高,我追踪了许多Airport
收集垃圾的实例。
我对此的解决方案是将转换class
为struct
。主要是它只是一个关键字变化,例外GetHashCode
和ToString
:
public override string ToString()
{
return Code ?? string.Empty;
}
public override int GetHashCode()
{
return Code?.GetHashCode() ?? 0;
}
处理使用情况default(Airport)
。
我的问题:
Airport
通常是创建一个类或构造一个好的解决方案,还是我通过创建类型来解决错误的问题/以错误的方式解决它?如果不是一个好的解决方案,那么什么是更好的解决方案?我的应用程序应如何处理使用的实例
default(Airport)
?一种类型的代码default(Airport)
对我的应用程序毫无意义,因此我一直if (airport == default(Airport) { throw ... }
在获取Airport
(及其Code
属性)实例对操作至关重要的地方进行操作。
注意:我查看了C#/ VB结构问题–如何避免零默认值的情况(对于给定的结构无效)?,以及在问我的问题之前是否使用struct,但是我认为我的问题足够不同,因此可以自己发表。
default(Airport)
问题的一种方法是简单地禁止默认实例。您可以通过编写一个参数的构造函数和投掷做,InvalidOperationException
或NotImplementedException
在里面。