我在考虑使用Tuple
类来存储程序中需要的2个整数信息(起始地址和结束地址)。
但是我发现Tuple
中的项目是只读的,因此如果我需要为一个项目设置值,我需要重新实例化一个 Tuple。
这个设计决策背后的原因是什么?
我在考虑使用Tuple
类来存储程序中需要的2个整数信息(起始地址和结束地址)。
但是我发现Tuple
中的项目是只读的,因此如果我需要为一个项目设置值,我需要重新实例化一个 Tuple。
这个设计决策背后的原因是什么?
元组(tuples)起源于函数式编程。在(纯)函数式编程中,一切都是不可变的 - 一个特定的变量在所有时间内只有一个定义,就像数学中一样。当将函数式风格集成到C#/.NET时,.NET设计师明智地遵循了相同的原则,尽管它最终是一种主要的命令式(混合?)语言。
注意: 虽然我怀疑元组是不可变的这一事实并没有让你的任务更加困难,但你可能也想使用匿名类型(或者只是简单的结构体)。
Tuple<A,B,C,...>
是一个公开字段结构体,则可以实现最佳的语义和性能。任何大小的公开字段结构体,如果被复制不到三次,则性能优于类;非常小的结构体无论被复制多少次都优于类,除非结构体很大,否则它们将优于类,除非被复制多次。唯一需要注意的是,如果一个结构体需要被装箱一次,那么类会比它更快,如果一个结构体需要经常被装箱,那么类会更胜一筹。 - supercat我不知道为什么没有这样的东西,但这正是我想要使用的。
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<T1,T2> 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<T1,T2> 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<T1,T2> 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<T1,T2> 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<T1,T2> 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<T1,T2> instance.
/// </summary>
/// <returns>The string representation of this System.WTuple<T1,T2> object.</returns>
public override string ToString()
{
StringBuilder sb = new StringBuilder();
sb.Append("(");
return ((IWTuple)this).ToString(sb);
}
#endregion
}
}
set
{
_item1 = value;
Console.WriteLine(_item1.ToString());
Console.WriteLine(base.Item1.ToString());
}
- BillW你只得到了ItemX属性的getter,没错,但我找到了一种方法,首先实例化一个带有空值的元组,然后在之后填充它们。
如果你做这样的事情:
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);