- 原文: Introducing C# 10
- 作者: Ken Bonny
- 翻译:Rwing
- 译文:[翻译] 预览 C# 10 的新东西
本周早些时候(译注:原文发表于 5 月 1 日),我关注了 Mads Torgersen 在 DotNet SouthWest 大会上的演讲,他是微软的 C# 语言的首席设计师。他概述了 C# 10 即将包含的很酷的一些新东西。让我们来快速浏览一下。
小さな免責事項として、これらの変更のほとんどはほぼ完了しています。しかし、まだ活発な開発中なので、C#10がリリースされたときにすべてが完全に真実になるとは保証できません。
struct record
他谈到的第一件事是,目前 record 的实现是使用一个 class 作为基础对象的。现在还会有一个 record struct 的变体可用,所以基础类型可以是一个值类型。区别在于,普通的 record 在函数之间传递的是引用,而 record struct 是其值的拷贝。 record struct 也会支持 with 运算符。
また、レコードに演算子を追加することもでき、両方のレコードタイプが可能です。
record Person(string Name, string Email)
{
public static Person operator +(Person first, Person second)
{
// logic goes here
}
}
required
C#チームの目標の1つは、オブジェクトの初期化を容易にすることです。このため、class、struct、record、またはstruct recordのプロパティにrequiredタグを追加できます。これらの属性を満たす必要がある。これはコンストラクタまたはオブジェクトの初期化で行うことができます。次の2つのクラスの定義は等価である。requiredキーワードを追加すると、Nameプロパティを設定せずにPersonをインスタンス化することはできません。コンパイラがエラーをスローしてコンパイルできません。
class Person
{
public required string Name { get; set; }
public DateTime DateOfBirth { get; set; }
}
class Person
{
public Person(string name) => Name = name;
public string Name { get; set; }
public DateTime DateOfBirth { get; set; }
}
field
属性をさらに改善するために、backing fieldからの完全な脱出が許可される。新しいキーワードfieldは、上記のフィールドにアクセスできます。setter属性とinit only属性の両方を使用できます。
class Person
{
public string Name { get; init => field = value.Trim(); }
public DateTime DateOfBirth { get; set => field = value.Date; }
}
with
在下一个版本中还会有一些有趣的小改进。其实中一个是匿名类型也将支持 with 运算符。
var foo = new
{
Name = "Foo",
Email = "foo@mail.com"
};
var bar = foo with {Name = "Bar"};
namespace
现在可以创建一个带有命名空间导入的文件,然后在任何地方都可以使用这个导入。例如,如果有一个很常用的命名空间,几乎在每个文件中都使用例如 Microsoft.Extensions.Logging.ILogger ,那么就可以在任何.cs 文件(我建议在 Program.cs 或专门的 Imports.cs )中添加一行 global using Microsoft.Extensions.Logging.ILogger,之后这个命名空间将可以在整个项目中使用。注意,这不适用于整个解决方案! 没有人能够预测哪些地方需要导入,所以它们被分组到每个项目中。
// 译注:原文并没有提供代码示例,为了更好方便大家理解私自添加了一个演示
// Program.cs 文件
global using System;
// Sample.cs 文件
// 可以不用再using System;
Console.WriteLine("foo");
その後、名前空間の最適化も行われます。名前空間はコードを囲む中括弧を必要とします。つまり、すべてのコードは少なくとも1回インデントされます。タブ(または4つのスペース)と画面スペースを節約するために、ファイル内の任意の場所に名前空間を追加すると、すべてのコードがその名前空間に属します。研究によると、ほとんどの場合、ファイル内のすべてのコードは同じ名前空間に属します。このシナリオを使用すると、ファイルサイズが減少します。これはソリューションでは明らかではないかもしれません(何千ものファイルが含まれていても)が、GitHub/GitLab/BitBucket/..。その規模では、スペースを節約できると思います。ファイル内に複数の名前空間を含めたい場合は、中括弧を使用するオプションが引き続き利用できます。
// 传统的方式 LegacyNamespace.cs
namespace LegacyNamespace
{
class Foo
{
// legacy code goes here
}
}
// 简化的方式 SimplifiedNamespace.cs
namespace SimplifiedNamespace;
class Bar
{
// awesome code goes here
}
lambda
ラムダ文にもクールな更新があります。コンパイラはラムダシグネチャを推論するためのより良いサポートを提供し、機能を追加することもできる。コンパイラがラムダを理解するのに役立つ戻り値の型を明示的に指定できます。
var f = Console.WriteLine;
var f = x => x; // 推断返回类型
var f = (string x) => x; // 推断签名
var f = [NotNull] x => x; // 添加特性
var f = [NotNull] (int x) => x;
var f = [return: NotNull] static x => x; // 添加特性
var f = T () => default; // 显式返回类型
var f = ref int (ref int x) => ref x; // 使用 ref
var f = int (x) => x; // 显式指定隐式输入的返回类型
var f = static void (_) => Console.Write("Help");
混乱しにくい機能の例を提供してくれてありがとうSchooley
interface
最後に、インターフェイスに静的メソッドとプロパティを指定することができます。インターフェイスにデフォルトの実装を追加するのと同じように、これは論争の的になるでしょう。好きじゃないわしかし、それは非常に興味深い。インターフェイスのデフォルト値を指定するか、作成メソッドを指定できるとします。
interface IFoo
{
static IFoo Empty { get; }
static operator +(IFoo first, IFoo second);
}
class Foo : IFoo
{
public static IFoo Empty => new Foo();
public static operator +(IFoo first, IFoo second) => /* do calculation here */;
}
就个人而言,我喜欢这些变化。我最喜欢的是对命名空间的改变和对接口的改进。总之,未来是光明的 C# 的。嗯嗯... (译注:这里作者玩了一个梗,原文 the future is seeing sharp,see sharp 发音类似 C# )
ありがとうございました。