.net 为什么元组的项目是只读的?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3131400/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-03 14:27:15  来源:igfitidea点击:

Why Tuple's items are ReadOnly?

.net.net-4.0readonlytuples

提问by Drake

I was thinking to use Tupleclass to store 2 integer information (StartAddress, EndAddress) I need in my program.

我正在考虑使用Tuple类来存储我的程序中需要的 2 个整数信息(StartAddress、EndAddress)。

But I discover that Tupleitems are ReadOnly, so if I need to set a value for an item, I need to re-instantiate a Tuple.

但是我发现Tuple项目是只读的,所以如果我需要为项目设置一个值,我需要重新实例化一个元组。

What is the reason behind this design decision?

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

采纳答案by Noldorin

Tuples originated in functional programming. In (purely) functional programming, everythingis immutable by design - a certain variable only has a single definition at all times, as in mathematics. The .NET designers wisely followed the same principle when integrating the functional style into C#/.NET, despite it ultimately being a primarily imperative (hybrid?) language.

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

Note: Though I suspect the fact that tuples are immutable doesn't really make your task much harder, there are also anonymous types (or perhaps just a simple struct) you might want to use.

注意:虽然我怀疑元组是不可变的这一事实并没有真正使您的任务变得更加困难,但您可能还想使用匿名类型(或者可能只是一个简单的结构)。

回答by xamid

I wonder why there is not such thing like this. However, it is what I prefer to use.

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

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

回答by Jonathan

You might want to try upgrading, as C# 7.0 introduces new language support for Tupleswhich (among other things) makes them mutable. (Under the hood, it uses ValueTuple, whose members are mutable.)

您可能想尝试升级,因为 C# 7.0 引入了对元组的新语言支持(除其他外)使它们可变。(在幕后,它使用ValueTuple,其成员是可变的。)

回答by Greg

You got only the getters of the ItemX properties, that's right, but I found a way to first instanciate a tupple with empty values and fill them afterwords.

你只有 ItemX 属性的 getter,没错,但我找到了一种方法来首先用空值实例化一个元组并在后面填充它们。

If you do something like this :

如果你做这样的事情:

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

The tplTemp passed as an out parameter will have it's 2 items values from the collection. So that's a way of doing in case this can help's someone.

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