Trong hệ thống của tôi, tôi thường xuyên hoạt động với mã sân bay ( "YYZ"
, "LAX"
, "SFO"
, vv), chúng luôn luôn theo cùng định dạng chính xác (3 lá thư, thể hiện dưới dạng chữ hoa). Hệ thống thường xử lý 25-50 mã (khác nhau) cho mỗi yêu cầu API, với tổng số hơn một nghìn phân bổ, chúng được chuyển qua nhiều lớp trong ứng dụng của chúng tôi và được so sánh khá bình thường.
Chúng tôi đã bắt đầu chỉ bằng cách chuyển các chuỗi xung quanh, hoạt động tốt một chút nhưng chúng tôi nhanh chóng nhận thấy rất nhiều lỗi lập trình bằng cách gửi mã sai ở đâu đó mã 3 chữ số được mong đợi. Chúng tôi cũng gặp phải các vấn đề trong đó chúng tôi phải thực hiện một so sánh không phân biệt chữ hoa chữ thường và thay vào đó là không, dẫn đến lỗi.
Từ đó, tôi quyết định dừng các chuỗi xung quanh và tạo một Airport
lớp, trong đó có một hàm tạo duy nhất lấy và xác nhận mã sân bay.
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);
}
}
Điều này làm cho mã của chúng tôi dễ hiểu hơn nhiều và chúng tôi đã đơn giản hóa việc kiểm tra đẳng thức, từ điển / tập hợp sử dụng. Bây giờ chúng ta biết rằng nếu các phương thức của chúng ta chấp nhận một Airport
thể hiện rằng nó sẽ hoạt động theo cách chúng ta mong đợi, thì nó đã đơn giản hóa việc kiểm tra phương thức của chúng ta thành kiểm tra tham chiếu null.
Tuy nhiên, điều tôi nhận thấy là bộ sưu tập rác đã chạy thường xuyên hơn, mà tôi đã theo dõi rất nhiều trường hợp Airport
thu thập.
Giải pháp của tôi cho việc này là chuyển đổi class
thành a struct
. Chủ yếu chỉ là thay đổi từ khóa, ngoại trừ GetHashCode
và ToString
:
public override string ToString()
{
return Code ?? string.Empty;
}
public override int GetHashCode()
{
return Code?.GetHashCode() ?? 0;
}
Để xử lý trường hợp default(Airport)
được sử dụng.
Những câu hỏi của tôi:
Việc tạo ra một
Airport
lớp hoặc cấu trúc một giải pháp tốt nói chung, hay tôi đang giải quyết vấn đề sai / giải quyết nó sai cách bằng cách tạo ra loại? Nếu nó không phải là một giải pháp tốt, thì giải pháp nào tốt hơn?Ứng dụng của tôi nên xử lý các trường hợp
default(Airport)
sử dụng như thế nào? Một loạidefault(Airport)
là vô nghĩa đối với ứng dụng của tôi, vì vậy tôi đã làmif (airport == default(Airport) { throw ... }
ở những nơi mà việc lấy một thể hiện củaAirport
(và thuộc tính của nóCode
) là rất quan trọng đối với hoạt động.
Lưu ý: Tôi đã xem lại các câu hỏi C # / VB struct - làm thế nào để tránh trường hợp có giá trị mặc định bằng 0, được coi là không hợp lệ đối với cấu trúc đã cho? và Sử dụng struct hoặc không trước khi đặt câu hỏi của tôi, tuy nhiên tôi nghĩ rằng các câu hỏi của tôi đủ khác nhau để đảm bảo bài đăng của chính nó.
default(Airport)
vấn đề là đơn giản là không cho phép các trường hợp mặc định. Bạn có thể làm điều đó bằng cách viết một hàm tạo không tham số và ném InvalidOperationException
hoặc NotImplementedException
trong đó.