更短的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);
}
}
}
也许一个不那么令人困惑的方法是:
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(...)
最重要的是你的代码对你和你的团队有意义。教条不应该成为选择样式的理由。