在“元组”中比“Item1”,“Item2”更好地命名

有没有办法使用Tuple类,但提供其中的项目的名称?

例如:

public Tuple<int, int, int int> GetOrderRelatedIds() 

这将返回OrderGroupId,OrderTypeId,OrderSubTypeId和OrderRequirementId的ID。

这将是很好的,让我的方法的用户知道哪个是哪个。 (当你调用方法时,结果是result.Item1,result.Item2,result.Item3,result.Item4,不清楚哪一个是哪个。)

(我知道我可以创build一个类来容纳所有的Ids,但是这些Ids已经拥有自己的类,并且为这个方法的返回值创build一个类似乎是愚蠢的。)

在C#7.0(Visual Studio 2017)中有一个新的构build:

 (string first, string middle, string last) LookupName(long id) 

不,没有办法做到这一点没有定义自己的types。

这是你所问的一个过于复杂的版本:

 class MyTuple : Tuple<int, int> { public MyTuple(int one, int two) :base(one, two) { } public int OrderGroupId { get{ return this.Item1; } } public int OrderTypeId { get{ return this.Item2; } } } 

为什么不上课呢?

使用.net 4你也许可以看看ExpandoObject ,但是,不要把它用于这个简单的情况,因为编译时错误会变成运行时错误。

 class Program { static void Main(string[] args) { dynamic employee, manager; employee = new ExpandoObject(); employee.Name = "John Smith"; employee.Age = 33; manager = new ExpandoObject(); manager.Name = "Allison Brown"; manager.Age = 42; manager.TeamSize = 10; WritePerson(manager); WritePerson(employee); } private static void WritePerson(dynamic person) { Console.WriteLine("{0} is {1} years old.", person.Name, person.Age); // The following statement causes an exception // if you pass the employee object. // Console.WriteLine("Manages {0} people", person.TeamSize); } } // This code example produces the following output: // John Smith is 33 years old. // Allison Brown is 42 years old. 

值得一提的是在一个方法中的匿名types ,但是如果你想返回它,你需要创build一个类。

 var MyStuff = new { PropertyName1 = 10, PropertyName2 = "string data", PropertyName3 = new ComplexType() }; 

如果你的项目的types是不同的,这是我为了让他们更直观的类。

这个类的用法:

 var t = TypedTuple.Create("hello", 1, new MyClass()); var s = t.Get<string>(); var i = t.Get<int>(); var c = t.Get<MyClass>(); 

源代码:

 public static class TypedTuple { public static TypedTuple<T1> Create<T1>(T1 t1) { return new TypedTuple<T1>(t1); } public static TypedTuple<T1, T2> Create<T1, T2>(T1 t1, T2 t2) { return new TypedTuple<T1, T2>(t1, t2); } public static TypedTuple<T1, T2, T3> Create<T1, T2, T3>(T1 t1, T2 t2, T3 t3) { return new TypedTuple<T1, T2, T3>(t1, t2, t3); } public static TypedTuple<T1, T2, T3, T4> Create<T1, T2, T3, T4>(T1 t1, T2 t2, T3 t3, T4 t4) { return new TypedTuple<T1, T2, T3, T4>(t1, t2, t3, t4); } public static TypedTuple<T1, T2, T3, T4, T5> Create<T1, T2, T3, T4, T5>(T1 t1, T2 t2, T3 t3, T4 t4, T5 t5) { return new TypedTuple<T1, T2, T3, T4, T5>(t1, t2, t3, t4, t5); } public static TypedTuple<T1, T2, T3, T4, T5, T6> Create<T1, T2, T3, T4, T5, T6>(T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6) { return new TypedTuple<T1, T2, T3, T4, T5, T6>(t1, t2, t3, t4, t5, t6); } public static TypedTuple<T1, T2, T3, T4, T5, T6, T7> Create<T1, T2, T3, T4, T5, T6, T7>(T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6, T7 t7) { return new TypedTuple<T1, T2, T3, T4, T5, T6, T7>(t1, t2, t3, t4, t5, t6, t7); } public static TypedTuple<T1, T2, T3, T4, T5, T6, T7, T8> Create<T1, T2, T3, T4, T5, T6, T7, T8>(T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6, T7 t7, T8 t8) { return new TypedTuple<T1, T2, T3, T4, T5, T6, T7, T8>(t1, t2, t3, t4, t5, t6, t7, t8); } } public class TypedTuple<T> { protected Dictionary<Type, object> items = new Dictionary<Type, object>(); public TypedTuple(T item1) { Item1 = item1; } public TSource Get<TSource>() { object value; if (this.items.TryGetValue(typeof(TSource), out value)) { return (TSource)value; } else return default(TSource); } private T item1; public T Item1 { get { return this.item1; } set { this.item1 = value; this.items[typeof(T)] = value; } } } public class TypedTuple<T1, T2> : TypedTuple<T1> { public TypedTuple(T1 item1, T2 item2) : base(item1) { Item2 = item2; } private T2 item2; public T2 Item2 { get { return this.item2; } set { this.item2 = value; this.items[typeof(T2)] = value; } } } public class TypedTuple<T1, T2, T3> : TypedTuple<T1, T2> { public TypedTuple(T1 item1, T2 item2, T3 item3) : base(item1, item2) { Item3 = item3; } private T3 item3; public T3 Item3 { get { return this.item3; } set { this.item3 = value; this.items[typeof(T3)] = value; } } } public class TypedTuple<T1, T2, T3, T4> : TypedTuple<T1, T2, T3> { public TypedTuple(T1 item1, T2 item2, T3 item3, T4 item4) : base(item1, item2, item3) { Item4 = item4; } private T4 item4; public T4 Item4 { get { return this.item4; } set { this.item4 = value; this.items[typeof(T4)] = value; } } } public class TypedTuple<T1, T2, T3, T4, T5> : TypedTuple<T1, T2, T3, T4> { public TypedTuple(T1 item1, T2 item2, T3 item3, T4 item4, T5 item5) : base(item1, item2, item3, item4) { Item5 = item5; } private T5 item5; public T5 Item5 { get { return this.item5; } set { this.item5 = value; this.items[typeof(T5)] = value; } } } public class TypedTuple<T1, T2, T3, T4, T5, T6> : TypedTuple<T1, T2, T3, T4, T5> { public TypedTuple(T1 item1, T2 item2, T3 item3, T4 item4, T5 item5, T6 item6) : base(item1, item2, item3, item4, item5) { Item6 = item6; } private T6 item6; public T6 Item6 { get { return this.item6; } set { this.item6 = value; this.items[typeof(T6)] = value; } } } public class TypedTuple<T1, T2, T3, T4, T5, T6, T7> : TypedTuple<T1, T2, T3, T4, T5, T6> { public TypedTuple(T1 item1, T2 item2, T3 item3, T4 item4, T5 item5, T6 item6, T7 item7) : base(item1, item2, item3, item4, item5, item6) { Item7 = item7; } private T7 item7; public T7 Item7 { get { return this.item7; } set { this.item7 = value; this.items[typeof(T7)] = value; } } } public class TypedTuple<T1, T2, T3, T4, T5, T6, T7, T8> : TypedTuple<T1, T2, T3, T4, T5, T6, T7> { public TypedTuple(T1 item1, T2 item2, T3 item3, T4 item4, T5 item5, T6 item6, T7 item7, T8 item8) : base(item1, item2, item3, item4, item5, item6, item7) { Item8 = item8; } private T8 item8; public T8 Item8 { get { return this.item8; } set { this.item8 = value; this.items[typeof(T8)] = value; } } } 

不,你不能命名元组成员。

中间将使用ExpandoObject而不是Tuple。

我想我会创build一个类,但另一种select是输出参数。

 public void GetOrderRelatedIds(out int OrderGroupId, out int OrderTypeId, out int OrderSubTypeId, out int OrderRequirementId) 

由于你的Tuple只包含整数,你可以用Dictionary<string,int>来表示它

 var orderIds = new Dictionary<string, int> { {"OrderGroupId", 1}, {"OrderTypeId", 2}, {"OrderSubTypeId", 3}, {"OrderRequirementId", 4}. }; 

但我不build议这样做。

为什么每个人都过得如此艰苦。 元组是用于相当临时的数据处理。 一直工作与元组将使代码非常难以理解。 创build类的一切可能会最终膨胀你的项目。

这是关于平衡,但是…

你的问题似乎是你想要一个类的东西。 为了完整起见,下面这个类还包含构造函数。


这是适当的模式

  • 自定义数据types
    • 没有进一步的function。 Getters和setter也可以用代码扩展,获取/设置私有成员的名字模式为“_orderGroupId”,同时也执行function代码。
  • 包含构造函数 如果所有的属性都是强制的,你也可以select只包含一个构造函数。
  • 如果你想使用所有的构造函数,像这样冒泡是避免重复代码的正确模式。

 public class OrderRelatedIds { public int OrderGroupId { get; set; } public int OrderTypeId { get; set; } public int OrderSubTypeId { get; set; } public int OrderRequirementId { get; set; } public OrderRelatedIds() { } public OrderRelatedIds(int orderGroupId) : this() { OrderGroupId = orderGroupId; } public OrderRelatedIds(int orderGroupId, int orderTypeId) : this(orderGroupId) { OrderTypeId = orderTypeId; } public OrderRelatedIds(int orderGroupId, int orderTypeId, int orderSubTypeId) : this(orderGroupId, orderTypeId) { OrderSubTypeId = orderSubTypeId; } public OrderRelatedIds(int orderGroupId, int orderTypeId, int orderSubTypeId, int orderRequirementId) : this(orderGroupId, orderTypeId, orderSubTypeId) { OrderRequirementId = orderRequirementId; } } 

或者,如果你想要它真的很简单:你也可以使用types初始值设定项:

 OrderRelatedIds orders = new OrderRelatedIds { OrderGroupId = 1, OrderTypeId = 2, OrderSubTypeId = 3, OrderRequirementId = 4 }; public class OrderRelatedIds { public int OrderGroupId; public int OrderTypeId; public int OrderSubTypeId; public int OrderRequirementId; } 

我将在总结中写入项目名称..所以通过hover在函数helloworld()上的文本将会说hello = Item1和world = Item2

helloworld(“Hi1,Hi2”);

  /// <summary> /// Return hello = Item1 and world Item2 /// </summary> /// <param name="input">string to split</param> /// <returns></returns> private static Tuple<bool, bool> helloworld(string input) { bool hello = false; bool world = false; foreach (var hw in input.Split(',')) { switch (hw) { case "Hi1": hello= true; break; case "Hi2": world= true; break; } } return new Tuple<bool, bool>(hello, world); }` 

这非常烦人,我预计C#的未来版本将解决这个需求。 我发现最简单的工作是使用不同的数据结构types,或者为了您的理智和读取您的代码的其他人的理智,重命名“项目”。

  Tuple<ApiResource, JSendResponseStatus> result = await SendApiRequest(); ApiResource apiResource = result.Item1; JSendResponseStatus jSendStatus = result.Item2; 

你可以编写一个包含Tuple的类。

您需要重写Equals和GetHashCode函数

和==和!=运算符。

 class Program { public class MyTuple { private Tuple<int, int> t; public MyTuple(int a, int b) { t = new Tuple<int, int>(a, b); } public int A { get { return t.Item1; } } public int B { get { return t.Item2; } } public override bool Equals(object obj) { return t.Equals(((MyTuple)obj).t); } public override int GetHashCode() { return t.GetHashCode(); } public static bool operator ==(MyTuple m1, MyTuple m2) { return m1.Equals(m2); } public static bool operator !=(MyTuple m1, MyTuple m2) { return !m1.Equals(m2); } } static void Main(string[] args) { var v1 = new MyTuple(1, 2); var v2 = new MyTuple(1, 2); Console.WriteLine(v1 == v2); Dictionary<MyTuple, int> d = new Dictionary<MyTuple, int>(); d.Add(v1, 1); Console.WriteLine(d.ContainsKey(v2)); } } 

将返回:

真正

真正