【问题标题】:How to name tuple properties?如何命名元组属性?
【发布时间】:2015-03-10 14:40:21
【问题描述】:

如何和“可能”组织从返回元组类型的方法返回参数名称, 举个例子

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:我想创建具有命名参数但没有新命名类型的对象。

【问题讨论】:

标签: c# tuples


【解决方案1】:

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

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

【讨论】:

  • 什么是命名约定?与参数名称相同(camelCase)?还是方法名(ProperCase)?
  • 将它们视为公共字段(或属性),我认为它们应该是适当的情况
  • 此选项适用于 ValueTuples,不适用于 Tuples!
【解决方案2】:

你需要声明一个帮助类来这样做。

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

您要返回的是匿名类型。顾名思义,你不知道它的名字是什么,所以你不能声明你的方法来返回它。

Anonymous Types (C# Programming Guide)

您不能声明字段、属性、事件或返回类型 将方法视为具有匿名类型。 同样,您不能声明 方法、属性、构造函数或索引器的形式参数 具有匿名类型。传递匿名类型或集合 包含匿名类型,作为方法的参数,您可以 将参数声明为类型对象。然而,这样做会挫败 强类型的目的。如果您必须存储查询结果或传递它们 在方法边界之外,考虑使用一个普通的命名结构 或类而不是匿名类型。

更新

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

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

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

【讨论】:

  • 请注意,您在此处定义的类型是可变的,而不是不可变的,并且与 Tuple 或匿名类型不同,它没有覆盖其值语义的相等语义。
  • 我认为通过将更新移至答案顶部可以改进此答案。
【解决方案3】:

现在从 C# v7.0 开始,可以命名元组属性,以前默认为 Item1Item2 等名称。

命名元组文字的属性

var myDetails = (MyName: "Foo", MyAge: 22, MyFavoriteFood: "Bar");
Console.WriteLine($"Name - {myDetails.MyName}, Age - {myDetails.MyAge}, Passion - {myDetails.MyFavoriteFood}");

控制台输出:

姓名 - Foo,年龄 - 22,激情 - 酒吧

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

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);
}

控制台输出:

员工详细信息: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

注意:我的代码 sn-ps 正在使用 C# v6 的字符串插值功能,详细说明 here

【讨论】:

  • 安装包 System.ValueTuple
【解决方案4】:

Tuple 无法做到这一点,不。为此,您需要创建自己的新命名类型。

【讨论】:

  • 现在可以在 C# 7.0 中使用
  • @toddmo:使用带有命名属性的元组有什么意义?仅使用普通类或匿名类型?只是问,因为我想不出原始可能性未涵盖的用例。
  • @Flater,我鼓励你提出这个问题。希望 C# 团队的负责人 Eric 能给你他们的想法。以下是新功能:blogs.msdn.microsoft.com/dotnet/2016/08/24/…
  • @toddmo Anders Hejlsberg 是 C# 团队的负责人。如果你指的是 Eric Lippert,他在几年前就离开了 C# 团队,并且从来都不是团队的负责人。
  • @Flater 当您只需要组合在一起的几个属性或从方法中创建一个简单的返回类型时,它们非常棒,即使创建一个简单的类型似乎也是一件苦差事。如果它是一个类型只能使用一次的一次性,它会特别有用。它有点像具有命名属性的匿名类型 :-) 如果您可以为一个元组声明一个别名以在多个地方使用,那将会更加有用。
【解决方案5】:

我通常创建一个派生自 Tuple 的新类型,并映射您的显式属性以返回基类的 ItemX 属性。 例如:

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

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

【讨论】:

  • 也许我没有抓住重点,但为什么要麻烦一个元组而不是创建一个标准类?
  • 它实现了IComparable 并覆盖了GetHashCode,因此相等性由Item1 和Item2 中的值定义。如果用作字典中的复合键(我的示例是从中派生的,请注意我忘记重命名类构造函数),则非常有用。虽然现在 c#7 命名元组是更好的解决方案。
【解决方案6】:

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

此方法可以通过 3 种方式编译: 1.) 将返回类型更改为对象 - 这将创建一个“匿名”类型,您可以稍后使用。如果您想稍后在不做一些额外工作的情况下访问“姓名”或“年龄”属性,这并不是特别有用。 2.) 将返回类型更改为动态 - 这将允许您访问“名称”和“年龄”属性,但会使整个程序(只是该方法所在的 DLL)稍微慢一些,因为使用动态需要抛出出一些强类型。 3.) 创建一个类并将其用作返回类型。

这里的示例代码:

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; }
        }

【讨论】:

    【解决方案7】:

    在我看来,当您想从单个方法返回或获取许多东西时,最好将其返回类型设为 CLASS,但如果您打算使用本身是 Class 的 Tuple,那么为了更好地命名这个新类应该继承自 Tuple .例如如下所述。

     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.
        }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-01-08
      • 2023-03-29
      • 2015-09-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多