2010-11-08 30 views
6

.NET C.L có loại Thiết lập không thay đổi không? Tôi lập trình trong một phương ngữ chức năng của C# và muốn làm điều gì đó nhưThiết lập không thể thay đổi trong .NET

new Set.UnionWith(A).UnionWith(B).UnionWith(C) 

Nhưng tốt nhất mà tôi có thể tìm thấy là HashSet.UnionWith, mà sẽ yêu cầu trình tự sau đây của các cuộc gọi:

HashSet composite = new HashSet(); 
composite.UnionWith(A); 
composite.UnionWith(B); 
composite.UnionWith(C); 

này sử dụng có độ đục rất tham chiếu, làm cho khó tối ưu hóa và hiểu được. Có cách nào tốt hơn để làm điều này mà không cần viết một loại thiết lập chức năng tùy chỉnh?

+0

này cũng có thể có liên quan đến http: // stackoverflow.com/questions/927181/immutable-collections – R0MANARMY

Trả lời

4

Cập nhật

Câu trả lời này đã được viết một số thời gian trước đây, và kể từ đó một bộ sưu tập bất biến đã được giới thiệu trong không gian tên System.Collections.Immutable.

Original câu trả lời

Bạn có thể cuộn ra phương pháp riêng của mình cho việc này:

public static class HashSetExtensions { 
    public static HashSet<T> Union<T>(this HashSet<T> self, HashSet<T> other) { 
    var set = new HashSet<T>(self); // don't change the original set 
    set.UnionWith(other); 
    return set; 
    } 
} 

Sử dụng nó như thế này:

var composite = A.Union(B).Union(C); 

Bạn cũng có thể sử dụng LINQ's Union, nhưng để có được một bộ, bạn sẽ cần phải chuyển kết quả đến hàm tạo HashSet:

var composite = new HashSet<string>(A.Union(B).Union(C)); 

Nhưng, bản thân HashSet có thể thay đổi. Bạn có thể thử sử dụng F#'s immutable set.

Ngoài ra, như đã đề cập trong các ý kiến ​​của ErikE, sử dụng Concat mang lại kết quả tương tự và có lẽ thực hiện tốt hơn:

var composite = new HashSet<string>(A.Concat(B).Concat(C)); 
+2

Mã này không đảm bảo tính bất biến sâu sắc. Nếu bạn sửa đổi cấu trúc bộ (ví dụ: những gì được chứa trong tập hợp), cấu trúc bộ gốc sẽ vẫn còn nguyên vẹn. Nhưng nếu bạn sửa đổi các mục trong tập hợp kết quả, các mục trong tập hợp gốc cũng sẽ được thay đổi. –

+2

Tính không thay đổi sâu chỉ được đảm bảo trong C# nếu các mục trong tập hợp không thể thay đổi được. Các thiết lập không thể thực thi nó trên riêng của mình. Ngoài ra, 'HashSet' là một tập hợp có thể thay đổi, vì vậy có lẽ bạn nên tìm các lớp khác bên ngoài BCL. –

+2

@ MerlynMorgan-Graham: Trạng thái của một tập bất biến của một số loại đối tượng lớp là tập hợp các định danh của các đối tượng được đề cập đến. Nếu tôi có danh sách 5 Số Nhận dạng Xe ô tô được in trên giấy hiển thị giả mạo, nó sẽ luôn đề cập đến năm chiếc xe giống nhau. Danh sách này không nên được coi là nói bất cứ điều gì về nơi những chiếc xe được, những gì màu sắc họ đang có, bao nhiêu dặm họ đã điều khiển, vv Tất cả những đặc điểm của xe là có thể thay đổi. Thực tế là nhiều tài sản của một chiếc xe có thể thay đổi, tuy nhiên, không làm cho danh sách những chiếc xe ít bất biến hơn. – supercat

9

mới ImmutableCollections có:

  • ImmutableStack<T>
  • ImmutableQueue<T>
  • ImmutableList<T>
  • ImmutableHashSet<T>
  • ImmutableSortedSet<T>
  • ImmutableDictionary<K, V>
  • ImmutableSortedDictionary<K, V>

Thông tin thêm here

Giới thiệu về công đoàn kiểm tra này qua:

[Test] 
public void UnionTest() 
{ 
    var a = ImmutableHashSet.Create("A"); 
    var b = ImmutableHashSet.Create("B"); 
    var c = ImmutableHashSet.Create("C"); 
    var d = a.Union(b).Union(c); 
    Assert.IsTrue(ImmutableHashSet.Create("A", "B", "C").SetEquals(d)); 
} 
Các vấn đề liên quan