更短的List构造语法

本文关键字:语法 List | 更新日期: 2023-09-27 18:04:13

对于c# 6.0,给定这个静态方法:

public static List<T> List<T>(params T[] items) => new List<T>(items);

和合适的using:

using static ListTest.ListUtils;

我可以使用List来构造列表:

var lsInt = List(10, 20, 30);
var lsStr = List("abc", "bcd", "cde");

不使用List法,可以通过以下方式进行施工:

var lsIntInitializer = new List<int>() { 10, 20, 30 };

名称List现在被用于类和方法。它似乎工作得很好,但除了不被认为是习惯用语之外,是否有任何技术原因为什么我不应该在这里使用List作为方法名?

我也可以使用list,但这不是习惯用法,因为方法往往是大写的。

注意,我对非惯用路线没有问题,但如果在这一领域有公认的做法,我想知道一下。

当然,c# 6.0和它的using static是一个美丽的新世界,所以可能只是没有足够的社区经验来处理这类事情。

language-ext项目使用类似的方法来构造ImmutableList对象。在这种情况下,他们使用名称list

摘自上述节选的完整工作示例如下:

using System;
using System.Collections.Generic;
using static ListTest.ListUtils;
namespace ListTest
{
    public static class ListUtils
    {
        public static List<T> List<T>(params T[] items) => new List<T>(items);
    }
    class Program
    {
        static void Main(string[] args)
        {
            var lsInt = List(10, 20, 30);
            var lsStr = List("abc", "bcd", "cde");
            var lsIntInitializer = new List<int>() { 10, 20, 30 };
            lsInt.ForEach(Console.WriteLine);
            lsStr.ForEach(Console.WriteLine);
        }
    }
}

更短的List构造语法

也许一个不那么令人困惑的方法是:

public static class List
{
    public static List<T> Create<T>(params T[] items) => new List<T>(items);
}

可以这样调用:

var lsInt = List.Create(10, 20, 30);

(当然没有using static;使用名为Create的方法导入一个类将会真的令人困惑)

这与不可变集合(ImmutableList, ImmutableArray等)使用的方法相同

Language-Ext的作者在这里。显然你知道我的看法。我现在使用List而不是list来构建Lst<T>,这是ImmutableList<T>的包装器。

我认为c#习惯用法的问题在于它们牢固地植根于Java/c# 1时代。如果这是你想要的编码风格,这是可以的。我想你可以说c#变得越来越像Scala,越来越不像Java,所以如果你想掌握c#中更新的函数工具,那么也许把你的习惯用语移向Scala(或f#)是有意义的。

我经常在这类讨论中看到@ErikE的一条评论:

对我来说,方法名应该是动词。如果List是一个动词,那么它不会创建一个列表,也不会要求返回一个列表,但它将执行列出的行为——例如将数字放入某个位置(并使用void返回类型)。所以这里不一致

这种"方法名应该是动词"的东西需要消亡,对"四人帮"写的任何东西的痴迷也需要消亡。这只是一种风格,一种技巧。你不会看到f#中的列表结构,例如(下图),并认为"我不可能理解它在做什么,因为没有动词"

let values = [1;2;3;4;5]

显然是在构造一个列表。那么c#

呢?
var values = new[] { 1, 2, 3, 4 };

"新",新什么?很明显,使用名称List作为构造函数与语言自己内置的列表构造(在本例中是数组,但重点仍然有效)一样具有描述性。

我现在为Language-Ext统一了一个样式,那就是:

  • 静态构造函数(如List)以大写字母开头,描述类型或类型将在构造后的状态(因此对于Option<T>,您使用Some(value)None构造)。
  • 静态类与f#中的模块类似,使用驼峰命名,例如:List.map, List.filter, Set.intersect等。
  • 方法通常是PascalCase。

这是一种两全其美的方法,对于那些希望他们的代码看起来像其他函数式语言的函数式程序员,你得到了List.filter(...),而对于那些发现这种风格"具有挑战性"的人,你得到了流畅的方法list.Filter(...)

最重要的是你的代码对你和你的团队有意义。教条不应该成为选择样式的理由。