Почему элементы Tuple доступны только для чтения? - PullRequest
49 голосов
/ 28 июня 2010

Я думал использовать класс Tuple для хранения двух целочисленных данных (StartAddress, EndAddress), которые мне нужны в моей программе.

Но я обнаружил, что Tuple элементы доступны только для чтения, поэтому если мне нужноустановить значение для элемента, мне нужно повторно создать экземпляр Tuple.

В чем причина этого дизайнерского решения?

Ответы [ 4 ]

50 голосов
/ 28 июня 2010

Кортежи возникли из функционального программирования .В (чисто) функциональном программировании все является неизменным по замыслу - определенная переменная всегда имеет только одно определение, как в математике.Разработчики .NET мудро следовали тому же принципу при интеграции функционального стиля в C # / .NET, несмотря на то, что в конечном итоге он был в первую очередь императивным (гибридным?) Языком.

Примечание: хотя я подозреваю, что кортежи неизменнына самом деле не делает вашу задачу намного сложнее, есть также анонимные типы (или просто простая структура), которые вы можете использовать.

2 голосов
/ 18 марта 2014

Интересно, почему нет такой вещи? Тем не менее, это то, что я предпочитаю использовать.

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
    }
}
0 голосов
/ 06 июля 2019

Возможно, вы захотите попробовать обновление, так как C # 7.0 представляет новую языковую поддержку для кортежей , что (среди прочего) делает их изменяемыми. (Под капотом он использует ValueTuple , члены которого являются изменяемыми.)

0 голосов
/ 13 февраля 2014

У вас есть только получатели свойств ItemX, это правильно, но я нашел способ сначала создать экземпляр поля с пустыми значениями и заполнить его последующими словами.

Если вы делаете что-то вроде этого:

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);

tplTemp, переданный в качестве параметра out, будет иметь значения из 2 элементов из коллекции.Так что это способ сделать, если это может кому-то помочь.

...