2010-06-28 17 views
42

Tôi đã nghĩ đến việc sử dụng lớp Tuple để lưu trữ 2 thông tin số nguyên (StartAddress, EndAddress) tôi cần trong chương trình của mình.Tại sao các mục của Tuple là ReadOnly?

Nhưng tôi phát hiện ra rằng Tuple mục là ReadOnly, vì vậy nếu tôi cần đặt giá trị cho một mục, tôi cần phải tạo lại một Tuple.

Lý do đằng sau quyết định thiết kế này là gì?

+1

Tôi nghĩ trong lập trình OO, Tuple thường chỉ là nhà phát triển lười biếng để mô tả cấu trúc dữ liệu của mình. Trong lập trình chức năng tuy nhiên nó là con bê vàng. Tôi không nói hoặc là tốt hay xấu và tôi cũng lười biếng một số lần. Chỉ có thể có các phương pháp hay nhất khác nhau cho các trường hợp sử dụng khác nhau. – Rbjz

Trả lời

41

Tuples có nguồn gốc từ functional programming. Trong (hoàn toàn) lập trình chức năng, mọi thứ là không thay đổi theo thiết kế - một biến nhất định chỉ có một định nghĩa duy nhất mọi lúc, như trong toán học. Các nhà thiết kế .NET một cách khôn ngoan theo nguyên tắc tương tự khi tích hợp phong cách chức năng vào C# /. NET, mặc dù nó cuối cùng là một ngôn ngữ chủ yếu (lai?). Lưu ý: Mặc dù tôi nghi ngờ thực tế là các bộ dữ liệu không thay đổi không thực sự khiến nhiệm vụ của bạn khó khăn hơn, cũng có các loại ẩn danh (hoặc có lẽ chỉ là một cấu trúc đơn giản) mà bạn có thể muốn sử dụng.

+9

Đó là các nhà thiết kế CLR, không phải nhà thiết kế C#. System.Tuple trong .NET 4 cũng được sử dụng ngầm bởi F #. –

+4

Có nhiều nhà phát triển BCL hơn các nhà thiết kế C# - đã có quyết định, bây giờ F # đã tham gia ổn định các ngôn ngữ .Net để có loại Tuple thống nhất. –

+1

Ahh người đi bộ không thể tránh khỏi. Ngoài ra, F # đã sử dụng các kiểu bộ tuple của riêng nó trước .NET 4.0 - dù sao nó cũng không liên quan. – Noldorin

-1

Bạn chỉ nhận được getters của các thuộc tính ItemX, đúng vậy, nhưng tôi đã tìm ra cách để tạo ra một tupple đầu tiên với các giá trị rỗng và điền chúng sau đó.

Nếu bạn làm điều gì đó như thế này:

Dictionary <string, Tuple<string, string>> mydic = new Dictionary<string,Tuple<string,string>>(); 
Tuple<string, string> tplTemp = new Tuple<string, string>("", ""); 
mydic.TryGetValue("akey", out tplTemp); 

Các tplTemp thông qua như là một tham số ra sẽ có nó là 2 mặt hàng giá trị từ bộ sưu tập. Vì vậy, đó là một cách để làm trong trường hợp điều này có thể giúp một ai đó.

+2

Đây không phải là cách để điền vào một Tuple với các giá trị. Tất cả những gì bạn đã làm là tạo một Tuple thứ hai và gán tplTemp cho giá trị của nó. Bạn mã tương đương với chỉ làm: tplTemp = new Tuple ("some", "values"); – gerrard00

1

Tôi tự hỏi tại sao không có những thứ như thế này. Tuy nhiên, đó là những gì tôi thích sử dụng.

namespace System 
{ 
    /// <summary> 
    /// Helper so we can call some tuple methods recursively without knowing the underlying types. 
    /// </summary> 
    internal interface IWTuple 
    { 
     string ToString(StringBuilder sb); 
     int GetHashCode(IEqualityComparer comparer); 
     int Size { get; } 
    } 

    /// <summary> 
    /// Represents a writable 2-tuple, or pair. 
    /// </summary> 
    /// <typeparam name="T1">The type of the tuple's first component.</typeparam> 
    /// <typeparam name="T2">The type of the tuple's second component.</typeparam> 
    public class WTuple<T1, T2> : IStructuralEquatable, IStructuralComparable, IComparable, IWTuple 
    { 
     private T1 _item1; 
     private T2 _item2; 

     #region ImplementedInterfaces 
     Int32 IStructuralEquatable.GetHashCode(IEqualityComparer comparer) 
     { 
      return comparer.GetHashCode(_item1); 
     } 
     Boolean IStructuralEquatable.Equals(Object other, IEqualityComparer comparer) { 
      if (other == null) return false; 
      WTuple<T1, T2> objTuple = other as WTuple<T1, T2>;//Tuple<t1, t2=""> objTuple = other as Tuple<t1, t2="">; 
      if (objTuple == null) { 
       return false; 
      } 
      return comparer.Equals(_item1, objTuple._item1) && comparer.Equals(_item2, objTuple._item2); 
     } 
     Int32 IStructuralComparable.CompareTo(Object other, IComparer comparer) 
     { 
      if (other == null) return 1; 
      WTuple<T1, T2> objTuple = other as WTuple<T1, T2>;//Tuple<t1, t2=""> objTuple = other as Tuple<t1, t2="">; 
      if (objTuple == null) 
      { 
       throw new ArgumentException("ArgumentException_TupleIncorrectType", "other");//ArgumentException(Environment.GetResourceString("ArgumentException_TupleIncorrectType", this.GetType().ToString()), "other"); 
      } 
      int c = 0; 
      c = comparer.Compare(_item1, objTuple._item1); 
      if (c != 0) return c; 
      return comparer.Compare(_item2, objTuple._item2); 
     } 
     Int32 IComparable.CompareTo(Object obj) 
     { 
      return ((IStructuralComparable)this).CompareTo(obj, Comparer<object>.Default); 
     } 
     Int32 IWTuple.GetHashCode(IEqualityComparer comparer) 
     { 
      return ((IStructuralEquatable)this).GetHashCode(comparer); 
     } 
     string IWTuple.ToString(StringBuilder sb) 
     { 
      sb.Append(_item1); 
      sb.Append(", "); 
      sb.Append(_item2); 
      sb.Append(")"); 
      return sb.ToString(); 
     } 
     int IWTuple.Size 
     { 
      get { return 2; } 
     } 
     #endregion 

     #region WTuple 
     /// <summary> 
     /// Initializes a new instance of the System.WTuple&lt;T1,T2&gt; class. 
     /// </summary> 
     /// <param name="item1">The value of the tuple's first component.</param> 
     /// <param name="item2">The value of the tuple's second component.</param> 
     public WTuple(T1 item1, T2 item2) 
     { 
      _item1 = item1; 
      _item2 = item2; 
     } 
     /// <summary> 
     /// Gets or sets the value of the current System.WTuple&lt;T1,T2&gt; object's first component. 
     /// </summary> 
     public T1 Item1 
     { 
      get { return _item1; } 
      set { _item1 = value; } 
     } 
     /// <summary> 
     /// Gets or sets the value of the current System.WTuple&lt;T1,T2&gt; object's second component. 
     /// </summary> 
     public T2 Item2 
     { 
      get { return _item2; } 
      set { _item2 = value; } 
     } 
     /// <summary> 
     /// Returns a value that indicates whether the current System.WTuple&lt;T1,T2&gt; object 
     /// is equal to a specified object. 
     /// </summary> 
     /// <param name="obj">The object to compare with this instance.</param> 
     /// <returns>true if the current instance is equal to the specified object; otherwise, 
     /// false.</returns> 
     public override Boolean Equals(Object obj) 
     { 
      return ((IStructuralEquatable)this).Equals(obj, EqualityComparer<object>.Default); 
     } 
     /// <summary> 
     /// Returns the hash code for the current System.WTuple&lt;T1,T2&gt; object. 
     /// </summary> 
     /// <returns>A 32-bit signed integer hash code.</returns> 
     public override int GetHashCode() 
     { 
      return ((IStructuralEquatable)this).GetHashCode(EqualityComparer<object>.Default); 
     } 
     /// <summary> 
     /// Returns a string that represents the value of this System.WTuple&lt;T1,T2&gt; instance. 
     /// </summary> 
     /// <returns>The string representation of this System.WTuple&lt;T1,T2&gt; object.</returns> 
     public override string ToString() 
     { 
      StringBuilder sb = new StringBuilder(); 
      sb.Append("("); 
      return ((IWTuple)this).ToString(sb); 
     } 
     #endregion 
    } 
} 
+1

Mã này hoàn toàn không sử dụng cấu trúc mà nó thừa kế từ nhưng đặt các giá trị Tuple cơ bản sau khi hàm tạo ... nơi chúng vẫn bất biến và không thể thay đổi. Việc sử dụng toán tử mới ở phía trước Properties là không cần thiết và không có hiệu lực. Thay đổi mã trong setter cho 'Item1 này, và thiết lập giá trị một lần xem để xem các giá trị trong cơ sở không bao giờ thay đổi: thiết lập { _item1 = value; Console.WriteLine (_item1.ToString()); Console.WriteLine (base.Item1.ToString()); } – BillW

+0

Cảm ơn bạn đã đề cập đến điều này. Tôi xin lôi. Trên thực tế, tôi không bao giờ thử nghiệm các chức năng ghi đè, nhưng chỉ sử dụng Item1 và Item2 (mà rõ ràng là hoạt động). Tôi đã tìm ra rằng sẽ không thể thay đổi mục nhập trong Tuple , do việc sử dụng các thuộc tính chỉ đọc, như tôi đã thấy ở đây: http://reflector.webtropy.com/default.aspx/[email protected]/[email protected]/untmp/DEVDIV_TFS/Dev10/Phát hành/RTMRel/ndp/clr/src/BCL/Hệ thống/Tuple @ cs/1305376/Tuple @ cs Tuy nhiên, tôi đã cập nhật mã, sao cho nó chỉ thực hiện các giao diện theo cách tương tự với Tuple . – xamid

Các vấn đề liên quan