C# 需要为数据结构(如元组或keyValuePair)提供建议,但类型是可变的

C# 需要为数据结构(如元组或keyValuePair)提供建议,但类型是可变的,c#,generics,data-structures,key-value,C#,Generics,Data Structures,Key Value,我需要一个类型,如Tuple或KeyValuePair类型,并带有设置其值的选项(可变类型)。 现有的泛型能满足这些需求吗 (在我看来,这本词典对我来说似乎有些过分了) 我也可以编写自己的类,但我希望已经实现了某种可变类型的KeyValuePair。不,没有。除非您考虑对象[]/COD>为一:(-) 注意,实现MutableTuple非常简单 一个可变元组的完整实现,几乎相当于元组(各种接口是公开实现的,而不是私下实现的)(部分基于元组的单一实现) 公共静态类可变元组 { 创建公共静态可变元组(

我需要一个类型,如
Tuple
KeyValuePair
类型,并带有设置其值的选项(可变类型)。 现有的泛型能满足这些需求吗

(在我看来,这本词典对我来说似乎有些过分了)


我也可以编写自己的类,但我希望已经实现了某种可变类型的
KeyValuePair

不,没有。除非您考虑<代码>对象[]/COD>为一:(-)

注意,实现
MutableTuple
非常简单

一个
可变元组
的完整实现,几乎相当于
元组
(各种接口是公开实现的,而不是私下实现的)(部分基于
元组
的单一实现)

公共静态类可变元组
{
创建公共静态可变元组(T1项1、T2项2、T3项3)
{
返回新的可变元组(item1、item2、item3);
}
}
[可序列化]
公共类可变元组:IComparable、IsstructuralEquatable、IsstructuralComparable
{
公共T1项1{get;set;}
公共T2项2{get;set;}
公共T3项3{get;set;}
公共可变元组(T1项1、T2项2、T3项3)
{
这个项目1=项目1;
本条第2项=第2项;
本条第3项=第3项;
}
公共覆盖布尔等于(对象对象对象)
{
返回此.Equals(obj,EqualityComparer.Default);
}
公共覆盖int GetHashCode()
{
返回此.GetHashCode(EqualityComparer.Default);
}
公共重写字符串ToString()
{
var sb=新的StringBuilder();
某人追加(该项1);
某人加上(“,”);
某人附加(本条第2款);
某人加上(“,”);
某人附加(此项3);
某人加上(“)”;
使某人返回字符串();
}
公共整数比较(对象对象对象)
{
返回this.CompareTo(obj,Comparer.Default);
}
公共布尔等于(对象对象对象、IEqualityComparer比较器)
{
if(obj==null)
{
返回false;
}
var tuple=obj作为可变元组;
返回tuple!=null&&(comparer.Equals(this.Item1,tuple.Item1)&&comparer.Equals(this.Item2,tuple.Item2))&&comparer.Equals(this.Item3,tuple.Item3);
}
public int GetHashCode(IEqualityComparer比较器)
{
未经检查
{
int hash=17;
hash=(hash*23)+comparer.GetHashCode(this.Item1);
hash=(hash*23)+comparer.GetHashCode(this.Item2);
hash=(hash*23)+comparer.GetHashCode(this.Item3);
返回散列;
}
}
公共int比较器(对象对象对象、IComparer比较器)
{
if(obj==null)
{
返回1;
}
var other=obj作为可变元组;
如果(其他==null)
{
抛出新ArgumentException();
}
int res=comparer.Compare(this.Item1,other.Item1);
如果(res!=0)
{
返回res;
}
res=comparer.Compare(this.Item2,other.Item2);
如果(res!=0)
{
返回res;
}
res=comparer.Compare(this.Item3,other.Item3);
返回res;
}
}
公共类可变KeyValuePair
{
公钥{get;set;}
公共TValue值{get;set;}
}

就是这样。

拥有可变元组的问题在于,您很容易多次引用同一元组,在一个地方更改值,而在其他您不希望更改的地方也会更改。因此,如果您确实使用可变tuple,您必须非常严格地在适当的位置克隆tuple,例如,如果您将其放入集合中

但是一个可变元组看起来像这样:

public class MutableTuple<T1, T2> {
    public T1 Item1 { get; set; }
    public T2 Item2 { get; set; }

    public MutableTuple(T1 item1, T2 item2) {
        Item1 = item1;
        Item2 = item2;
    }
}
公共类可变元组{
公共T1项1{get;set;}
公共T2项2{get;set;}
公共可变元组(T1项1,T2项2){
第1项=第1项;
第2项=第2项;
}
}

存在一个可变对,但它有两个问题:(1)它不是泛型/类型安全的。(2) 这是一种可变值类型。@JeppeStigNielsen你说得对。。。我不知道。我们甚至可以补充一个问题,那就是对于元组,它是一个
struct
:-),他们非常努力地思考并选择了
class
es。第二个(它是一个可变值类型)是一个特性,而不是bug:-)一个很好的完整答案。注释很少,1)为什么使用非泛型的相等比较器和哈希代码来导致装箱?2) 用字符串生成器代替6个字符串连接值吗?3)
Mutuple
将是一个更好的命名:D@nawfal1)因为接口
是按这种方式完成的。2) 可能是的,但这取决于子字符串的长度。例如,如果
this.Item1
==
this.Item2
=
this.Item3
==”,则简单的字符串串联会更好。但请记住,这是一个代码示例。您必须为不同数量的参数实现它(
Tuple
最多八个)。使用8个参数时,
StringBuilder
会更快。3) 我对命名不是很在行。当我工作时,我试着让我的同事或老板选择名字。1)
isstructuralequatable
可能是这样,但在不改变结果行为的情况下,以一种通用方式进行
public override bool Equals(object obj)
不是更好吗?但是我看到框架本身实现了如您所示:(.3)我是在开玩笑:)还不够。默认情况下,元组具有相等和哈希代码实现。
public class MutableKeyValuePair<TKey, TValue>
{
    public TKey Key { get; set; }
    public TValue Value { get; set; }
}
public class MutableTuple<T1, T2> {
    public T1 Item1 { get; set; }
    public T2 Item2 { get; set; }

    public MutableTuple(T1 item1, T2 item2) {
        Item1 = item1;
        Item2 = item2;
    }
}