よくわかんないままこれ見つけて弄ってみて、わかんないながらも「なんでこれできるように作ってないの?><」って思ったから、わかんないけどたぶんC# にもあると便利?><(?)
polymorphism - Existential types in C#? - Stack Overflow https://stackoverflow.com/questions/32486531/existential-types-in-c
たとえば E が existential type で D が動的ディスパッチする系の型だとして、 Vec<E> だとベクタの要素は同じ型 (同じ内部表現の値) であることがたぶん確信できるけど、 Vec<D> だと要素の型は実はバラバラかもしれない、みたいな。
とはいえ、そういった内部表現を隠蔽するのが目的で existential type や動的ディスパッチを使うなら、それ自体は問題にならなくて、結局は動的であることのオーバーヘッドが気になるというだけの話になりそう
https://mastodon.cardina1.red/@lo48576/101920508524525423
この説明はちょっと違ったかも、存在型はたとえば「ユーザが指定した Interface を実装する何らかの型」とかであって、ポインタ+仮想関数テーブルとはまた別の意味になっているので
めっっっっちゃ雑に言うなら、存在型は「引数の型としては型パラメータとして振る舞い、戻り値の型としては『コンパイラにしか指定できない内部的な名前』として振る舞う」みたいなイメッジでとりあえず困らないかも
たとえば C++ のクロージャは型名を指定できないので、 auto で雑に受けるか std::function で受けるわけですが、前者では関数であると縛りをつけられないし、後者だと実行時オーバーヘッドがあります。
Rust で同じことをすると let による型指定なしの束縛と Box<dyn Fn()> などが相当するわけですが、これ以外にも impl Fn() という指定もできます。
たとえばクロージャを返す
fn f() -> impl Fn() {
|| println!("hello")
}
は、「何度でも呼べる関数として振る舞う何かを返す」ということは述べるけど、 std::function のようなオーバーヘッドはない (わざと付けることもできるけど)
典型的には「この関数は i64 のイテレータであるような何らかの型を返すことは保証するけど、それが具体的にどのような型であるかは教えたくないよ (i64 のイテレータであること以外の一切の保証を与えたくないよ)」というケースなどで有用。ある種のカプセル化、内部表現の隠蔽ですね
これ読みながら思ったのは、C# Delphi(?)/Java(?)で言う所のInterface・・・?><(ぜんぜん違う?><;)
型システムの理論からみるSwiftの存在型(Existential Type) - Qiita https://qiita.com/ukitaka/items/a993b5d7ed5ae84b1b52
そういえば最近気づいたけど、これDelphiっぽさ><
WebRequest.Create Method (System.Net) | Microsoft Docs https://docs.microsoft.com/en-us/dotnet/api/system.net.webrequest.create?view=netframework-4.7.2