【问题标题】:Can tuple literals in C# 7.0 enable aspect oriented programmingC# 7.0 中的元组文字可以启用面向方面的编程吗
【发布时间】:2017-12-23 18:38:27
【问题描述】:

我指的是这里描述的元组文字:https://blogs.msdn.microsoft.com/dotnet/2016/08/24/whats-new-in-csharp-7-0/#comment-321926

喜欢元组文字的想法。

但是,我预见到需要大量查找 返回元组中项目的顺序,并且想知道我们如何解决这个问题。

例如,将元组中的项目名称作为身份定义方面而不是顺序不是更有意义吗?或者有没有办法做到这一点,我没有看到?

例如:假设 NextEmployee() 是一些我没有源代码的库方法,也没有特别详细的文档记录,假设它返回 (firstname: “jamie”, lastname: “hince”, id: 102348) 给我,我说:

(string lastname, var _, int __) = NextEmployee(); // I only need the last name

编译器会愉快地将名字分配给姓氏,或者发出警告或错误。为什么不将姓氏映射到姓氏?

如果我们不必记住元组中姓氏的索引,我会看到允许更松散耦合的架构,并且可以只要求像这样的“姓氏”方面。

【问题讨论】:

  • 不,小心!字段的顺序很重要,而不是名称。编译器将(firstname: “jamie”, lastname: “hince”, id: 102348) 转换为(Item1: “jamie”, Item2: “hince”, Item3: 102348)。你真的不能通过名称访问字段,这都是编译器糖
  • 元组只是变量的包。您描述的是 C# 8 中的 records

标签: tuples language-features c#-7.0 valuetuple


【解决方案1】:

元组只是一个变量包。作为变量,您可以分配任何可分配给变量类型的值,而不管变量名称如何。

名称仅作为变量名称的指示。返回值的唯一区别是编译器使用TupleElementNames attribute 持久化元组元素的名称。

事实上,即使存在名称,如果您不使用与通常相同的名称,编译器也会警告您,这是一个错误并且仍然有效的语法:

(string firstname, string lastname, int id) NextEmployee()
    => (apples: "jamie", potatos: "hince", oranges: 102348);
/*
Warning CS8123 The tuple element name 'apples' is ignored because a different name is specified by the target type '(string firstname, string lastname, int id)'.
Warning CS8123 The tuple element name 'potatos' is ignored because a different name is specified by the target type '(string firstname, string lastname, int id)'.
Warning CS8123 The tuple element name 'oranges' is ignored because a different name is specified by the target type '(string firstname, string lastname, int id)'.
*/

你在这里使用的语法:

(string lastname, var _, int __) = NextEmployee();

不是元组声明语法,而是创建LastName变量、_变量和__变量的元组解构语法。

这些都是产生相同结果的等价物:

  • (var lastname, var _, var __) = NextEmployee(); // or any combination ofvarand type names
  • var (lastname, _, __) = NextEmployee();

要声明一个元组来接收方法的返回,你需要声明一个元组变量:

  • (string firstname, string lastname, int id) t = NextEmployee();
  • var t = NextEmployee();

但您的意图似乎是忽略 LastNameid 值:

(_, string lastname, _) = NextEmployee(); // declares a lastname variable and ignores firstname and id

但如果你真的写了(string lastname, _, _) = NextEmployee();,那么你就是用返回的字符串“变量”firstname的值来分配一个名为lastname的本地字符串变量。

请记住,元组不是实体。它们是一组值。如果您使用的库使用元组作为实体,请注意该库可能存在其他问题。

【讨论】:

    【解决方案2】:

    为什么不呢?好吧,因为底层运行时甚至不知道名称。

    编译器必须在编译期间执行此操作。我们在哪里停下来?错别字、大小写等呢? 在我看来,目前的方式还可以。

    如果您对此主题有不同的看法,请在 github 上的官方语言设计存储库中提出问题,提出问题:

    https://www.github.com/dotnet/csharplang

    Paulo 已经很好地解释了技术细节,所以我不会重复。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2010-11-26
      • 2010-11-27
      • 2010-11-24
      • 2010-09-08
      • 1970-01-01
      • 1970-01-01
      • 2010-09-18
      • 2012-09-03
      相关资源
      最近更新 更多