C# 3.0 C#3.0元组等价物(适用于穷人)
我偶尔会在C#3.0中寻找模拟元组概念的方法。随着时间的推移,我已经有了各种“穷人”的实现,这里有一些: 基本对象数组:C# 3.0 C#3.0元组等价物(适用于穷人),c#-3.0,tuples,C# 3.0,Tuples,我偶尔会在C#3.0中寻找模拟元组概念的方法。随着时间的推移,我已经有了各种“穷人”的实现,这里有一些: 基本对象数组: object[] poorTuple = new object[]{foo,bar,baz}; // basic object array 更强类型的,HoHoHo KeyValuePair<TypeA, KeyValuePair<TypeB, TypeC>> poorTuple; KeyValuePair-poorTuple; 实现一个可以使用
object[] poorTuple = new object[]{foo,bar,baz}; // basic object array
更强类型的,HoHoHo
KeyValuePair<TypeA, KeyValuePair<TypeB, TypeC>> poorTuple;
KeyValuePair-poorTuple;
实现一个可以使用类型推断(从中提取)的类
公共静态类元组{
公共静态元组创建{
返回新元组(foo,bar);
}
}
//后来:
var data=Tuple.Create(“foo”,42);
问题:
您可以创建匿名类型,其功能类似于元组,但使用有用的名称除外:
var itemsWithChildCounts
= myObjects.Select(x => new { Name = x.Name, Count = x.Children.Count() });
我不喜欢C#中的类型推断,因为它被滥用得太多了。当然,这是一个非常酷的功能,但人们在这种情况下滥用它 在这种情况下,我将显式地指定类型,以避免对类型的混淆(例如,42可能是长的、字节的或短的) 那么,为什么不创建一个简单的元组类呢?它只需几行就可以实现。如果你很懒,你甚至可以为你的元组类写一些扩展方法。这使生活更容易,但也更干净
你不明白用一个“奇特”的元组类来代替你介绍的泛型类有什么意义(除了类型推断) 对于1-2:我更喜欢实现自己的元组类。你偷的是一个不错的实现。它应该很有效 对于3:这是我的经验法则——只要您打算在多个方法中重用此功能(具有相同类型和相同含义),或者如果您在任何公共API中使用它,我认为是时候用您的特定类型实现一个“真实”类了
既然你征求了我的意见,我会一直创建一个类型——我想不出一个不这样做的理由
通常情况下,您会发现实际需要该类型(主要用途是在集合中存储两个项或从方法调用返回两个项——在这两种情况下,如果这些项不密切相关,则可能是做错了).以下是2007年4月版Visual Studio杂志中比尔·瓦格纳的通用元组代码
公共结构元组:IEquatable
{
私有只读T1优先;
公共T1优先
{
获取{return first;}
}
私有只读T2秒;
公共T2秒
{
获取{return second;}
}
公共元组(T1 f,T2 s)
{
第一个=f;
秒=秒;
}
#区域可容纳成员
公共布尔等于(元组其他)
{
先返回。等于(其他先返回)和
第二,相等(其他,第二);
}
公共覆盖布尔等于(对象对象对象)
{
if(对象是元组)
返回这个.Equals((元组)obj);
其他的
返回false;
}
公共覆盖int GetHashCode()
{
返回first.GetHashCode()ˆsecond.GetHashCode();
}
#端区
}
我认为在程序中引入新的值集是有意义的,创建一个新类型是很好的。例如,如果您正在编写一个复杂的计算器,则创建一个复杂的数字类型。如果您真的只想将几个变量“粘合”在一起,那么元组可能是更好的选择。假设您有一个从控制台收集两个数字的简单函数。。。您可能会这样做:
static void GetNumbers(out int x, out int y) { ... }
...
int x, y;
GetNumbers(out x, out y);
我认为当一个“getter”函数有一个返回值时,它通常是有意义的,但在这种情况下它没有意义,因为我不能真正有两个返回值。我可以去做一种叫做TwoNumber的新类型并使用它,但我认为这很快就会成为一个问题而不是解决方案。如果C#有元组,我可能可以做如下操作:
static (int, int) GetNumbers() { ... }
...
int x, y;
(x, y) = GetNumbers();
// this class is implemented much like yours only with C++
template<typename T1, typename T2> class tuple { ... }
...
template<typename T1, typename T2> tuple<T1, T2>& tie(T1 a, T2 b) { ... }
...
template<typename T1, typename T2> tuple<T1, T2> get_numbers() { ... }
...
int x, y;
tie(x, y) = get_numbers();
现在真正有趣的问题是:尽管C#没有这个特性,但我能用库自己实现它吗?您建议的代码只是一个开始,但不允许我像在第二个示例中那样分配。我不确定C++,但是在C++中,如果函数返回值是引用类型,函数调用可以是赋值操作符的左操作数,那么就可以在C++中真正接近这个。考虑以下事项:
static (int, int) GetNumbers() { ... }
...
int x, y;
(x, y) = GetNumbers();
// this class is implemented much like yours only with C++
template<typename T1, typename T2> class tuple { ... }
...
template<typename T1, typename T2> tuple<T1, T2>& tie(T1 a, T2 b) { ... }
...
template<typename T1, typename T2> tuple<T1, T2> get_numbers() { ... }
...
int x, y;
tie(x, y) = get_numbers();
<代码> //此类仅与C++实现
模板类元组{…}
...
模板元组&tie(T1-a,T2-b){…}
...
模板元组get_numbers(){…}
...
int x,y;
tie(x,y)=获取_个数字();
我想说这真是太接近了。。。而不是(x,y)=
我们有tie(x,y)=
。如果您对实现细节感兴趣,我将向您介绍TR1库,我是在那里第一次了解到这一点的:
所以要把这一切带回C#3.0。。。如您所示,我们当然可以创建一个通用的元组类,但是我们可以创建一个像tie这样的函数来“解包”C#中的元组吗?我没试过,听起来很有趣。如果没有类似的东西,我不愿意让一个C#元组库通过我的代码扩散 匿名类型不能被传递到创建它们的方法之外,因此它们在r中的用处要小得多