如何命名元组属性?

How to name tuple properties?

"could be" 如何从 return 元组类型和参数名称的方法中组织 return, 举个例子

private static Tuple<string, string> methodTuple()
{
    return new {Name = "Nick", Age = "Twenty"}; /*exception because need to new Tuple<string, string>(){Item1 = "Nick", Item2 = "Twenty"}o*/
}

并且调用参数像 methodTuple.Name 不像 methodTuple.Item1....N

这可能吗?

UPD:我想创建具有命名参数但没有新命名类型的对象。

Tuple 做不到这一点,不。您需要创建自己的新命名类型才能执行此操作。

您需要声明一个助手 class 才能这样做。

public class MyResult
{
    public string Name { get; set; }
    public string Age { get; set; }
}

您尝试 return 的是匿名类型。顾名思义,你不知道它的名字是什么,所以你不能向它声明你的方法return。

Anonymous Types (C# Programming Guide)

You cannot declare a field, a property, an event, or the return type of a method as having an anonymous type. Similarly, you cannot declare a formal parameter of a method, property, constructor, or indexer as having an anonymous type. To pass an anonymous type, or a collection that contains anonymous types, as an argument to a method, you can declare the parameter as type object. However, doing this defeats the purpose of strong typing. If you must store query results or pass them outside the method boundary, consider using an ordinary named struct or class instead of an anonymous type.

更新

C#7 引入了语言中内置的元组支持,它带有命名元组

(string name, int age) methodTuple()
{
    (...)
}

在 docs.microsoft.com 上阅读更多内容:https://docs.microsoft.com/en-us/dotnet/articles/csharp/csharp-7#tuples

不幸的是,使用 "Tuple" 类型是不可能的,因为它在 MSDN 中被定义为 "Item1...N"。所以这个例外是有效的。

该方法可以通过3种方式编译: 1.) 将 return 类型更改为对象 - 这将创建一个 "anonymous" 类型,您可以稍后使用。如果您想稍后访问 "Name" 或 "Age" 属性 而无需一些额外的工作,它就不是特别有用。 2.) 将 return 类型更改为动态 - 这将允许您访问 "Name" 和 "Age" 属性,但会使整个程序(只是此方法所在的 DLL)确实位于)稍微慢一些,因为使用动态需要丢弃一些强类型。 3.) 创建一个 class 并将其用作 return 类型。

示例代码在这里:

private static object ObjectTuple()
        {
            return new { Name = "Nick", Age = "Twenty" };
        }

        private static dynamic DynamicTuple()
        {
            return new { Name = "Nick", Age = "Twenty" };
        }

        private static Temp TempTuple()
        {
            return new Temp{ Name = "Nick", Age = "Twenty" };
        }

        class Temp
        {
            public string Name { get; set; }
            public string Age { get; set; }
        }

我通常会创建一个派生自 Tuple 的新类型,并将您的显式属性映射到 return 基础 class 的 ItemX 属性。 例如:

public class Person : Tuple<string, string>
{
    public Key(string name, string age) : base(name, age) { }

    public string Name => Item1;
    public string Age => Item2;
}

在 C# 7.0 (Visual Studio 2017) 中有一个新选项可以做到这一点:

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

按照我的说法,当你想 return 或从一个方法中得到很多东西时,最好将其 return 类型设置为 CLASS 但如果你打算使用 Tuple本身是 Class 那么为了更好地命名这个新的 class 应该继承自元组。例如下面提到。

 public CustomReturn ExecuteTask( int a, string b, bool c, object d )
        {
        // Calling constructor of CustomReturn Class to set and get values
          return new CustomReturn(a,b,c,d);
        }

        internal class CustomReturn 
        // for tuple inherit from Tuple<int,string,bool,object,double>
        { 
          //for tuple public int A{ get {this.Item1} private set;}

          public int A{get;private set;}
          public string B{get;private set;}
          public bool C{get;private set;}
          public object D{get;private set;}

          public CustomReturn (int a, string b, bool c, object d )
              // use this line for tuple ": base( obj, boolean )"
            {
              this.A = a;
              this.B = b;
              this.C = c;
              this.D = d;
            }

        }

    Main(args)
    {
      var result = ExecuteTask( 10, "s", true, "object" );
      // now if u have inherited Tuple for CustomReturn class then 

      // on doing result. you will get your custom name as A,B,C,D for //Item1,Item2,Item3,Item4 respectively also these Item1,Item2,Item3,Item4 will also be there.
    }

从 C# v7.0 开始,现在可以为元组属性指定自定义名称。早些时候,它们曾经有默认名称,如 Item1Item2 等。

命名元组文字的属性:

var personDetails = (Name: "Foo", Age: 22, FavoriteFood: "Bar");
Console.WriteLine($"Name - {personDetails.Name}, Age - {personDetails.Age}, Favorite Food - {personDetails.FavoriteFood}");

控制台输出:

Name - Foo, Age - 22, Favorite Food - Bar

从方法返回元组(具有命名属性)

static void Main(string[] args)
{
    var empInfo = GetEmpInfo();
    Console.WriteLine($"Employee Details: {empInfo.firstName}, {empInfo.lastName}, {empInfo.computerName}, {empInfo.Salary}");
}

static (string firstName, string lastName, string computerName, int Salary) GetEmpInfo()
{
    //This is hardcoded just for the demonstration. Ideally this data might be coming from some DB or web service call
    return ("Foo", "Bar", "Foo-PC", 1000);
}

控制台输出:

Employee Details: Foo, Bar, Foo-PC, 1000

创建具有命名属性的元组列表

var tupleList = new List<(int Index, string Name)>
{
    (1, "cow"),
    (5, "chickens"),
    (1, "airplane")
};

foreach (var tuple in tupleList)
    Console.WriteLine($"{tuple.Index} - {tuple.Name}");

控制台输出:

1 - cow  
5 - chickens  
1 - airplane

注意:此 post 中的代码片段使用了 C# 的字符串插值功能,该功能在版本 6 中引入,详见 here

现在您可以使用 C# 中的元组 Name 来实现

对于 Lambda 表达式:

private static (string Name, string Age) methodTuple() => ( "Nick", "Twenty" );

private static (string Name, string Age) methodTuple()
{
    return ( "Nick", "Twenty" );
}

不要使用 class 元组类型 使用基本类型在元组中设置名称。