
2003年4月、C#1.2がリリースされ、それ以降、すべてのバージョンにメジャーバージョンのみが含まれるようになりました。
そして今、 githubの公式roslynページによると、バージョン7.1と7.2が機能しています。
バージョン7.1を試すには、プレリリースのVisual Studioをインストールする必要があります。 ダウンロードは公式サイトからダウンロードできます
ソリューションのプロパティに移動することにより、使用する言語のバージョンを選択できます。
次に、私が気に入った新しい言語機能についてお話したいと思います。
非同期メイン(バージョン7.1で計画)
現在、ほぼ完全に非同期のプログラムは非常に一般的です。
これまでのところ、Mainはvoidまたはintです。 また、文字列の配列の形式で引数を含めることもできます。 これで、いくつかの新しいオーバーロードが追加されます。
public static Task Main(); public static Task<int> Main(); public static Task Main(string[] args); public static Task<int> Main(string[] args);
CLRは非同期エントリポイントをサポートしていないため、コンパイラー自体がボイラープレートコードを作成します(つまり、voidをTaskに変換できる追加コードを自動的に挿入します)
およそそのようなコードはコンパイラーによって生成されます:
async Task<int> Main(string[] args) { // - } // « » int $GeneratedMain(string[] args) { return Main(args).GetAwaiter().GetResult(); }
私は、多くの人と同じように、 この機能を言語の第7バージョンで期待していました。
リテラルのデフォルト(バージョン7.1で計画)
Visual BasicとC#の機能はほぼ同じです。 しかし、言語自体には特定の違いがあります。 C#にnullがあり、VB.NETにNothingがあるとします。 したがって、Nothingは、このタイプのデフォルト値を表すどのシステムタイプにも変換できません。 nullがそうでないことは明らかです。 ただし、デフォルト値はnullでもかまいません。
これで、式のデフォルト(T)が適用されました。 そのアプリケーションの例を考えてみましょう。 パラメータとして文字列の配列を受け取るメソッドがあるとします:
void SomeMethod(string[] args) { }
メソッドを実行して、デフォルトの配列文字列値を次のように渡すことができます。
SomeMethod(default(string[]));
しかし、デフォルトを書くことができるのに、なぜデフォルト(文字列[])を書くのでしょうか?
ここでは、C#7.1以降、デフォルトのリテラルを使用できます。 メソッドにデフォルト値を渡す以外は、他に何ができますか? たとえば、オプションのパラメーターの値として使用できます。
void SomeMethod(string[] args = default) { }
または、変数をデフォルト値で初期化します。
int i = default;
現在の値がデフォルト値であるかどうかも確認できます。
int i = 1; if (i == default) { } // int 0 if (i is default) { } //
できないことは何ですか? デフォルトリテラルを使用できない方法の次の例:
const int? y = default; if (default == default) if (default is T) // is default var i = default throw default default as int; // 'as' reference
読み取り専用参照(バージョン7.2で計画)
値ごと(値ごと)にメソッドに構造体を送信すると、オブジェクトがコピーされます。これはリソースの価値があります。 また、参照オブジェクトの値のみを送信する必要がある場合もあります。 この場合、開発者はメモリを節約するためにrefリンクを介して値を送信しますが、値を変更できないというコメントを書き込みます。 これは、ベクトルオブジェクトと行列オブジェクトを使用した数学演算で特に頻繁に発生します。
私たちを待っているものの明確な例:
static Vector3 Add (ref readonly Vector3 v1, ref readonly Vector3 v2) { // ! v1 = default(Vector3); // ! v1.X = 0; // ! foo(ref v1.X); // return new Vector3(v1.X +v2.X, v1.Y + v2.Y, v1.Z + v2.Z); }
この関数はまだプロトタイプ状態ですが、その必要性は確信しています。 推奨されるオプションの1つは、ref readonlyの代わりにinキーワードを使用することです
static Vector3 Add (in Vector3 v1, in Vector3 v2) { return new Vector3(v1.X +v2.X, v1.Y + v2.Y, v1.Z + v2.Z); }
なぜrefは読み取り専用のほうが明確ですか? しかし、inは短いためです。
デフォルトでインターフェースメソッド(バージョン8.0で計画)
これらのメソッドはすぐには表示されません。
インターフェイスを実装するクラスまたは構造があると想像してください。 そして今、彼らはインターフェイスから1つのメソッドの実装を継承できるようになります(!)またはこのメソッドのバージョンを実装する必要があります。
インターフェースでの実装の概念自体はかなり奇妙に聞こえます。 Java 8にはデフォルトのインターフェイスメソッドがありますが、C#を使用する開発者も同様の機能が必要でした。
この機能により、API作成者は既存のすべてのインターフェイス実装のメソッドコードを変更できます。
例は明確なはずです。 SomeMethodメソッドに実装が含まれるインターフェイスがあるとします。
interface IA { void SomeMethod() { WriteLine(" SomeMethod IA"); } }
次に、インターフェースを実装するクラスを作成します。
class C : IA { }
そして、インターフェースのインスタンスを作成します。
IA i = new C();
これで、SomeMethodメソッドを呼び出すことができます。
i.SomeMethod(); // " SomeMethod IA"
想定されるタプル名(バージョン7.1で計画)
この機能により、場合によってはタプルの名前を指定しないことができます。 特定の条件下では、タプル要素は推定上の名前になります。
例:
(f1:x.f1、f2:x?.F2)と書く代わりに、単に(x.f1、x?.F2)と書くことができます。
この場合のタプルの最初の要素はf1、2番目のf2という名前になります
これで、タプルは名前なしになります(その要素にアクセスできるのはitem1、item2 ...のみです)
推測名は、LINQでタプルを使用する場合に特に便利です
// c result f1 f2 var result = list.Select(c => (c.f1, c.f2)).Where(t => t.f2 == 1);
マイナス面
この機能を導入する主な欠点は、C#7.0との互換性です。 例:
Action y = () => M(); var t = (x: x, y); ty(); // extension method y(),
しかし、7.0と7.1のリリース間の期間は短いため、このわずかな互換性違反に耐えることができます。
実際、7.0を使用している場合、すでにVisual Studioは次のことを警告しています。
タプル要素名「y」が推測されます。 推定名で要素にアクセスするには、言語バージョン7.1以降を使用してください。
完全なサンプルコード:
class Program { static void Main(string[] args) { string x = "demo"; Action y = () => M(); var t = (x: x, y); ty(); // extension method y(), } private static void M() { Console.WriteLine("M"); } } public static class MyExtensions { public static void y(this (string s, Action a) tu) { Console.WriteLine("extension method"); } }
.NET 4.6.2以前を使用している場合、例を試すには、NuGetパッケージSystem.ValueTupleをインストールする必要があります。