首页 文章

为什么Tuple的项目是ReadOnly?

提问于
浏览 475
44

我想用 Tuple 类来存储我程序中需要的2个整数信息(StartAddress,EndAddress) .

但我发现 Tuple 项是ReadOnly,所以如果我需要为一个项设置一个值,我需要重新实例化一个元组 .

这个设计决定背后的原因是什么?

3 回答

  • 45

    我想知道为什么没有这样的事情 . 但是,这是我更喜欢使用的 .

    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
        }
    }
    
  • 2

    元组起源于functional programming . 在(纯粹的)函数式编程中,一切都是设计不可变的 - 某个变量在任何时候都只有一个定义,就像在数学中一样 . .NET设计人员在将功能风格集成到C#/ .NET时明智地遵循了相同的原则,尽管它最终是一种主要的命令式(混合?)语言 .

    注意:虽然我怀疑元组是不可变的并不会让你的任务变得更加困难,但是你也可能想要使用匿名类型(或者只是一个简单的结构) .

  • -2

    你只获得了ItemX属性的getter,这是正确的,但是我找到了一种方法来首先使用空值设置一个tupple并填充它们 .

    如果您这样做:

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

    作为out参数传递的tplTemp将具有来自集合的2个项值 . 所以这是一种做法,以防万一这可以帮助某人 .

相关问题