Nếu mục đích của bạn là cấm phân công trong thời gian biên soạn, hơn bạn phải tuân theo nhiệm vụ của người xây dựng và người định cư riêng. Tuy nhiên nó có rất nhiều nhược điểm - bạn không thể sử dụng khởi tạo mới thành viên, cũng không phải xml deseralization và vv
tôi sẽ đề nghị một cái gì đó như thế này:
public class IssuerRecord
{
public string PropA { get; set; }
public IList<IssuerRecord> Subrecords { get; set; }
}
public class ImmutableIssuerRecord
{
public ImmutableIssuerRecord(IssuerRecord record)
{
PropA = record.PropA;
Subrecords = record.Subrecords.Select(r => new ImmutableIssuerRecord(r));
}
public string PropA { get; private set; }
// lacks Count and this[int] but it's IReadOnlyList<T> is coming in 4.5.
public IEnumerable<ImmutableIssuerRecord> Subrecords { get; private set; }
// you may want to get a mutable copy again at some point.
public IssuerRecord GetMutableCopy()
{
var copy = new IssuerRecord
{
PropA = PropA,
Subrecords = new List<IssuerRecord>(Subrecords.Select(r => r.GetMutableCopy()))
};
return copy;
}
}
IssuerRecord ở đây là nhiều hơn nữa mô tả và hữu ích. Khi bạn vượt qua nó ở một nơi khác, bạn có thể dễ dàng tạo ra phiên bản bất biến. Mã hoạt động trên bất biến nên có logic chỉ đọc, vì vậy nó không thực sự quan tâm nếu nó là cùng loại với IssuerRecord. Tôi tạo ra một bản sao của mỗi lĩnh vực thay vì chỉ gói các đối tượng bởi vì nó vẫn có thể được thay đổi ở một nơi khác, nhưng nó có thể không cần thiết đặc biệt là cho các cuộc gọi đồng bộ tuần tự. Tuy nhiên, an toàn hơn là lưu toàn bộ bản sao bất biến vào một số bộ sưu tập "cho sau này". Nó có thể là một trình bao bọc cho các ứng dụng khi bạn muốn một số mã cấm sửa đổi nhưng vẫn có khả năng nhận các cập nhật cho trạng thái đối tượng.
var record = new IssuerRecord { PropA = "aa" };
if(!Verify(new ImmutableIssuerRecord(record))) return false;
nếu bạn nghĩ theo thuật ngữ C++, bạn có thể thấy ImmutableIssuerRecords là "IssuerRecord const". Bạn phải sử dụng extracare để bảo vệ các đối tượng được sở hữu bởi đối tượng bất biến của bạn, đó là lý do tại sao tôi đề nghị tạo một bản sao cho tất cả trẻ em (ví dụ Subrecords).
ImmutableIssuerRecord.Subrecors là IEnumerable ở đây và thiếu Count và [], nhưng IReadOnlyList đang đến 4.5 và bạn có thể sao chép từ tài liệu nếu muốn (và dễ dàng di chuyển sau này).
có cách tiếp cận khác là tốt, chẳng hạn như Freezable:
public class IssuerRecord
{
private bool isFrozen = false;
private string propA;
public string PropA
{
get { return propA; }
set
{
if(isFrozen) throw new NotSupportedOperationException();
propA = value;
}
}
public void Freeze() { isFrozen = true; }
}
mà làm cho mã dễ đọc hơn một lần nữa, và không cung cấp bảo vệ thời gian biên dịch. nhưng bạn có thể tạo các đối tượng như bình thường và sau đó đóng băng chúng sau khi chúng đã sẵn sàng.
Mẫu trình tạo cũng là điều cần xem xét nhưng nó thêm quá nhiều mã "dịch vụ" từ quan điểm của tôi.
Có điều gì đó bên ngoài lớp cần đặt giá trị hay chính lớp đó có thể đặt giá trị? Nếu lớp có thể làm điều đó, thì bạn có thể có một hàm tạo parameterless. –
Xem: http://stackoverflow.com/questions/355172/how-to-design-an-immutable-object-with-complex-initialization?rq=1 – aquinas
Bạn đang khởi tạo các thuộc tính này ngay bây giờ như thế nào? –