C〓〓の中の9つの“黒の魔法”
私たちは
これらの高度な言語機能は、コンパイラが書いたもの(「黒の魔法」)なのか、それとも拡大(騒动)できる「アヒルのタイプ」なのかを見てみましょう。
まずリストを作ってみます。このカタログを見て判断してみてもいいです。「黒の魔法」といいますか?それとも「アヒルのタイプ」ですか? LINQ動作は、IEnumerable<T>タイプと; async/awaitとTask/ValueTaskタイプです。 式ツリー、Expression<T>タイプと; 補間文字列とFormatable Stringタイプ。 yield returnとIEnumerable<T>タイプ; foreachサイクル、IEnumerable<T>タイプと; usingキーワードは、IDisposableとインターフェースする。 TNullableタイプと; の任意のタイプのIndex/Range汎型動作。 1.
「黒の魔法」ではなく、「アヒルのタイプ」です。
前のブログで述べたように、
「黒の魔法」ではなく、「アヒルのタイプ」です。は、先にt.GetAwaiter()の方法を呼び出し、待ち受けaを取得する。 ブールタイプbを取得するためにa.Is Complettedを呼び出します。 b=trueであれば、a.GetResult()を直ちに実行し、実行結果を取得する。 b=falseであれば、状況を見ます。
a ICritical NotifyComprationが実現されていない場合は、(a as INotifyCompration).OComplected(action)を実行します。
もしaがICritical NotifyComprationを実現したら、(a as ICritical NotifyCompration).OComplected(action)を実行します。
実行はその後一時停止し、OComplettedが完了したら再度状態マシンに戻ります。
関心のある人は、
通常の
実行開始
第1回、時間:17:38-スレッド番号:1
第2回、時間:17:38-スレッド番号:1
第3回、時間:17:38:05-スレッド番号:1
第4回、時間:17:38-スレッド番号:1
実行完了
注意定義された
3.表現ツリー、
は「黒魔術」であり、「操作空間」はなく、タイプが
以下のコードのように:
「黒の魔法」です。「操作空間」はありません。
タイプが
5.
「黒の魔法」ですが、補足説明があります。
したがって、
6.
アヒルのタイプです。操作空間があります。
7.
はい、そうでもないです。
しかし、資源を解放するための需要は依然としてあります。どうすればいいですか?「アヒルのタイプ」が来ました。手書きで
は「黒の魔法」であり、
サンプルコードは以下の通りです。
「黒の魔法」と「アヒルのタイプ」があります。操作空間があります。
しかし、配列はまた違っています。
しかし、同時に「アヒル」タイプでもあります。コードに
上記のように、
ここでC〓〓の中の9つの「黒い魔法」についての文章を紹介します。これまでの文章を検索したり、下記の関連記事を見たりしてください。これからもよろしくお願いします。
C#
が非常に先進的な言語であることを知っています。これらの「構文糖」はあまりにも使いやすく、C#
コンパイラが死んだものだと思われてしまうことがあります。これらの高度な言語機能は、コンパイラが書いたもの(「黒の魔法」)なのか、それとも拡大(騒动)できる「アヒルのタイプ」なのかを見てみましょう。
まずリストを作ってみます。このカタログを見て判断してみてもいいです。「黒の魔法」といいますか?それとも「アヒルのタイプ」ですか?
C#
操作は、LINQ
タイプと「黒の魔法」ではなく、「アヒルのタイプ」です。
IEnumerable<T>
はLINQ
によって発行された新しい機能であり、データを非常に便利に操作することができる。今はC# 3.0
年が経ちました。機能はまだ強化されていますが、他の言語よりずっと便利です。前のブログで述べたように、
12
は必ずしもLINQ
に基づいていなくてもいいです。一つのタイプを定義し、必要なIEnumerable<T>
表現を実現すればいいです。
void Main()
{
var query =
from i in new F()
select 3;
Console.WriteLine(string.Join(",", query)); // 0,1,2,3,4
}
class F
{
public IEnumerable<int> Select<R>(Func<int, R> t)
{
for (var i = 0; i < 5; ++i)
{
yield return i;
}
}
}
2.LINQ
、LINQ
/select
タイプと「黒の魔法」ではなく、「アヒルのタイプ」です。
.Select
はasync/await
にリリースされ、非同期プログラムを容易に行うことができ、その本質は状態機械である。Task
の本質は、ValueTask
というタイプの次の名前のインターフェースを探すことであり、このインターフェースはasync/await
またはC# 5.0
に継承されたクラスを返さなければならない。もしaがICritical NotifyComprationを実現したら、(a as ICritical NotifyCompration).OComplected(action)を実行します。
実行はその後一時停止し、OComplettedが完了したら再度状態マシンに戻ります。
関心のある人は、
async/await
にアクセスすることができます。具体的な仕様説明:https://github.com/dotnet/csharplang/blob/master/spec/expressions.md通常の
GetAwaiter()
はINotifyCompletion
に基づくものであり、次のように「騒動作」を用いて、単一スレッドのICriticalNotifyCompletion
を実現することができる。
static Action Tick = null;
void Main()
{
Start();
while (true)
{
if (Tick != null) Tick();
Thread.Sleep(1);
}
}
async void Start()
{
Console.WriteLine(" ");
for (int i = 1; i <= 4; ++i)
{
Console.WriteLine($" {i} , :{DateTime.Now.ToString("HH:mm:ss")} - :{Thread.CurrentThread.ManagedThreadId}");
await TaskEx.Delay(1000);
}
Console.WriteLine(" ");
}
class TaskEx
{
public static MyDelay Delay(int ms) => new MyDelay(ms);
}
class MyDelay : INotifyCompletion
{
private readonly double _start;
private readonly int _ms;
public MyDelay(int ms)
{
_start = Util.ElapsedTime.TotalMilliseconds;
_ms = ms;
}
internal MyDelay GetAwaiter() => this;
public void OnCompleted(Action continuation)
{
Tick += Check;
void Check()
{
if (Util.ElapsedTime.TotalMilliseconds - _start > _ms)
{
continuation();
Tick -= Check;
}
}
}
public void GetResult() {}
public bool IsCompleted => false;
}
運転効果は以下の通りです。実行開始
第1回、時間:17:38-スレッド番号:1
第2回、時間:17:38-スレッド番号:1
第3回、時間:17:38:05-スレッド番号:1
第4回、時間:17:38-スレッド番号:1
実行完了
注意定義された
GetResult()
を作成するには、IsComplete
を使用しなければならない必要がない。3.表現ツリー、
Github
タイプは「黒魔術」であり、「操作空間」はなく、タイプが
Task.Delay()
である場合にのみ、表現ツリーとして作成されます。
はTaskEx.Delay()
であり、TaskCompletionSource<T>
とともに発表されたもので、遠見のある「黒の魔法」である。以下のコードのように:
Expression<Func<int>> g3 = () => 3;
コンパイラで翻訳されます。
Expression<Func<int>> g3 = Expression.Lambda<Func<int>>(
Expression.Constant(3, typeof(int)),
Array.Empty<ParameterExpression>());
4.補間文字列とasync/await
タイプ「黒の魔法」です。「操作空間」はありません。
Expression<T>
はExpression<T>
に発行され、これまで多くの言語で同様の機能が提供されてきた。タイプが
である場合にのみ、異なるコンパイル結果が発生します。
FormattableString x1 = $"Hello {42}";
string x2 = $"Hello {42}";
コンパイラの生成結果は以下の通りです。
FormattableString x1 = FormattableStringFactory.Create("Hello {0}", 42);
string x2 = string.Format("Hello {0}", 42);
その本質は、C# 3.0
を呼び出してタイプを作成することである。5.
LINQ
、FormattableString
タイプと;「黒の魔法」ですが、補足説明があります。
は、C# 6.0
のためのもの以外に、FormattableString
、FormattableStringFactory.Create
、yield return
、IEnumerable<T>
のために使用されてもよい。したがって、
yield return
を用いてIEnumerable<T>
/IEnumerable
のIEnumerator<T>
の動作をシミュレートするなら、比較的簡単である。
var seq = GetNumbers();
seq.MoveNext();
Console.WriteLine(seq.Current); // 0
seq.MoveNext();
Console.WriteLine(seq.Current); // 1
seq.MoveNext();
Console.WriteLine(seq.Current); // 2
seq.MoveNext();
Console.WriteLine(seq.Current); // 3
seq.MoveNext();
Console.WriteLine(seq.Current); // 4
IEnumerator<int> GetNumbers()
{
for (var i = 0; i < 5; ++i)
yield return i;
}
IEnumerator
――「サンデー」はC#
にリリースされます。6.
C++
サイクル、Java
タイプとアヒルのタイプです。操作空間があります。
generator<T>
は、必ずしも組み合わせて使用する必要はないyield return
タイプではなく、オブジェクトがC# 2.0
方法がある限り、
void Main()
{
foreach (var i in new F())
{
Console.Write(i + ", "); // 1, 2, 3, 4, 5,
}
}
class F
{
public IEnumerator<int> GetEnumerator()
{
for (var i = 0; i < 5; ++i)
{
yield return i;
}
}
}
また、foreach
がオブジェクトによって実現された場合、IEnumerable<T>
非同期ループも同様に使用することができる。
async Task Main()
{
await foreach (var i in new F())
{
Console.Write(i + ", "); // 1, 2, 3, 4, 5,
}
}
class F
{
public async IAsyncEnumerator<int> GetAsyncEnumerator()
{
for (var i = 0; i < 5; ++i)
{
await Task.Delay(1);
yield return i;
}
}
}
foreach
はIEnumerable<T>
でGetEnumerator()
と一緒に発表されたものです。具体的には私が以前書いた「コードデモンストレーションC菗各バージョンの新機能」が見られます。7.
GetAsyncEnumerator()
キーワード、await foreach
インターフェースはい、そうでもないです。
await foreach
及び通常のC# 8.0
は
キーワードを使用しており、using
インターフェースに基づく必要がある。IDisposable
と
は別の物語です。
は勝手に移動することができないので、引用タイプ――托管ヒープはメモリの移動を許可します。using
はIDisposable
との関係を許可しません。これはref struct
を継承することを含みます。IAsyncDisposable
もref struct
です。しかし、資源を解放するための需要は依然としてあります。どうすればいいですか?「アヒルのタイプ」が来ました。手書きで
ref struct
の方法を書くことができます。どのインターフェースを受け継ぐ必要がありません。
void S1Demo()
{
using S1 s1 = new S1();
}
ref struct S1
{
public void Dispose()
{
Console.WriteLine(" ");
}
}
同じ道理で、もし
インターフェースを使うならば:
async Task S2Demo()
{
await using S2 s2 = new S2();
}
struct S2 : IAsyncDisposable
{
public async ValueTask DisposeAsync()
{
await Task.Delay(1);
Console.WriteLine("Async ");
}
}
8.
、
タイプとは「黒の魔法」であり、
だけがDispose()
を受け入れることができ、IAsyncDisposable
はT?
の値を直接受け取ることができます。サンプルコードは以下の通りです。
int? t1 = null;
Nullable<int> t2 = null;
int t3 = null; // Error CS0037: Cannot convert null to 'int' because it is a non-nullable value type
生成コードは以下の通りである(Nullable<T>
はNullable<T>
と全く同じで、コンパイルに失敗したコードをスキップした)。
IL_0000: nop
IL_0001: ldloca.s 0
IL_0003: initobj valuetype [System.Runtime]System.Nullable`1<int32>
IL_0009: ldloca.s 1
IL_000b: initobj valuetype [System.Runtime]System.Nullable`1<int32>
IL_0011: ret
9.任意のタイプのT?
汎用動作「黒の魔法」と「アヒルのタイプ」があります。操作空間があります。
Nullable<T>
は、
に発行されており、インデックス位置をnull
のように操作しやすく、対応する値を取り出すことができる。以前は
などの複雑な操作が必要でしたが、今はとても簡単です。
string url = "https://www.super-cool.com/product/7705a33a-4d2c-455d-a42c-c95e6ac8ee99/summary";
string productId = url[35..url.LastIndexOf("/")];
Console.WriteLine(productId);
発生コードは以下の通りです。
string url = "https://www.super-cool.com/product/7705a33a-4d2c-455d-a42c-c95e6ac8ee99/amd-r7-3800x";
int num = 35;
int length = url.LastIndexOf("/") - num;
string productId = url.Substring(num, length);
Console.WriteLine(productId); // 7705a33a-4d2c-455d-a42c-c95e6ac8ee99
これにより、null
コンパイラはint?
を無視し、呼び出しNullable<int>
に直接翻訳した。しかし、配列はまた違っています。
var range = new[] { 1, 2, 3, 4, 5 }[1..3];
Console.WriteLine(string.Join(", ", range)); // 2, 3
発生コードは以下の通りです。
int[] range = RuntimeHelpers.GetSubArray<int>(new int[5]
{
1,
2,
3,
4,
5
}, new Range(1, 3));
Console.WriteLine(string.Join<int>(", ", range));
これは確かにIndex/Range
タイプを作成し、Index/Range
を呼び出して、完全に「黒の魔法」に属していることが分かります。しかし、同時に「アヒル」タイプでもあります。コードに
C# 8.0
属性とPython
方法が実装されている限り、Substring
を呼び出すことができます。
var range2 = new F()[2..];
Console.WriteLine(range2); // 2 -> -2
class F
{
public int Length { get; set; }
public IEnumerable<int> Slice(int start, int end)
{
yield return start;
yield return end;
}
}
発生コードは以下の通りです。
F f = new F();
int length2 = f.Length;
length = 2;
num = length2 - length;
string range2 = f.Slice(length, num);
Console.WriteLine(range2);
締め括りをつける上記のように、
C#
の「黒の魔法」は確かに多いですが、「アヒルのタイプ」もたくさんあります。「騒动」の「操作空間」はとても大きいです。Index/Range
はアヒルのタイプの元祖であるSubstring
を追加すると伝えられています。その時、「操作空間」はきっと今よりもっと大きくて、とても楽しみにしています。ここでC〓〓の中の9つの「黒い魔法」についての文章を紹介します。これまでの文章を検索したり、下記の関連記事を見たりしてください。これからもよろしくお願いします。