- 1 名前:デフォルトの名無しさん [2016/06/29(水) 04:39:09.19 ID:sT3gw8va.net]
- ■Visual Studio 2013 Community & Express(無償の統合開発環境)等はこちら
www.visualstudio.com/downloads/ ■コードを貼る場合はこちら ideone.com/ ■前スレ C#, C♯, C#相談室 Part88 [転載禁止]©2ch.net peace.2ch.net/test/read.cgi/tech/1437808445/ C#, C♯, C#相談室 Part89 peace.2ch.net/test/read.cgi/tech/1443271409/ C#, C♯, C#相談室 Part90 echo.2ch.net/test/read.cgi/tech/1455160063/ ■次スレは>>970が建てる事。 建てられない場合は他を指定する事。
- 357 名前:デフォルトの名無しさん [2016/08/27(土) 09:04:35.71 ID:SmFG8gRK.net]
- ク ク || プ //
ス ク ス | | │ // / ス | | ッ // ク ク ||. プ // / // ス ク ス _ | | │ // / ̄ ̄\ / ス ─ | | ッ // / _ノ .\ / // | ( >)(<) ___ . | ⌒(__人__) ./ ⌒ ⌒\ | ` Y⌒l / (>) (<)\ . | . 人__ ヽ / ::::::⌒(__人__)⌒ \ ヽ }| | | ` Y⌒ l__ | ヽ ノ、| | \ 人_ ヽ / . /^l / / ,─l ヽ \
- 358 名前:デフォルトの名無しさん mailto:sage [2016/08/27(土) 09:18:21.32 ID:xncZCRpk.net]
- ポリモフィズム過負荷で歪なクラスを量産するよりはよい
- 359 名前:デフォルトの名無しさん mailto:sage [2016/08/27(土) 09:56:58.93 ID:gXVhUUHW.net]
- 型で分岐するのがどうして問題かというと、
後で型を追加したときに分岐の箇所を自分で探して条件を追加しなきゃいけなくなるから。 ちゃんとした関数型だと、パターンマッチで分岐させるような型って type Shape = Rectangle(double x, double y, double w, double h) | Circle(double x, double y, double r); みたいな感じでクローズしておくんだよ。 これでShapeがとりうる全ての型をコンパイラが認識できるから、 Shapeに型を新たに追加したら>>329がコンパイルエラーになってくれる。 イメージ的には 列挙体 + タプル に近いかな。OO言語の超強力なクラスとは全然異なるもの。 このように、パターンマッチは根が深いからにわか言語が中途半端に導入するとおかしなことになる。
- 360 名前:デフォルトの名無しさん mailto:sage [2016/08/27(土) 10:14:58.12 ID:xncZCRpk.net]
- データベースやXMLで不定形データ受け取って
パースした後の分岐に使うくらいかな
- 361 名前:デフォルトの名無しさん mailto:sage [2016/08/27(土) 10:17:36.05 ID:xPu9ULSF.net]
- >>346
モジュールの配布面倒くさそう パターンをを追加したら参照元コード全部追記してねって全ユーザーに通知するの?
- 362 名前:デフォルトの名無しさん mailto:sage [2016/08/27(土) 12:08:15.98 ID:vp5ltHnS.net]
- >>346
しかしそれだと書く側にとってはOOPの方がいいが。 機能追加がクラス追加で対応できるとき、 OOP: 既存部分に一切手を入れる必要はない。 FP: 既存部分も書き直す必要がある。 普通はどう見ても退化だよ。 書き直す部分がSyntaxErrorで見つかるのは便利だけど、 OOPでもそのクラスの全メソッドを列挙するのは簡単なので、漏れる事もない。 OOPは実際の詳細なクラス毎の動作はその部分のコードからは読みとれない。 それがswitchの方がいいという人の意見なのだろうけど、 大概の場合は読みとれないのは低位記述のみであって、読みとる必要がないから問題ない。 >>329にしてもGetAreaメソッドの方がいいし、 本家の例にしてもExplainMyselfメソッドの方がいい。 本来はメソッドとしてくくれないswitch分岐に使えばいいのだろうけど、 本家にしてもそのいい例を探せなかったということじゃないか。 つまり要らない子。
- 363 名前:デフォルトの名無しさん mailto:sage [2016/08/27(土) 18:13:53.32 ID:gff3j1Ec.net]
- C#はjsのオブジェクトリテラルを導入すべきだ
C#の匿名型は書きにくいし見辛い
- 364 名前:デフォルトの名無しさん mailto:sage [2016/08/27(土) 19:31:49.76 ID:p93C1zWb.net]
- つまりパターンマッチはオブジェクト指向とはきわめて相性が悪いって事か
まあ、型チェックと代入が一発でできる機能だけなら便利に使える場面もあるだろうけど
- 365 名前:デフォルトの名無しさん mailto:sage [2016/08/27(土) 19:54:25.56 ID:0MFbcQeG.net]
- 相性が悪いんじゃなくて使い分けだと思う
上ででたShapeでは各クラスが面積を出すメソッドを持っててもべつにいいだろうけど GUI側で図形の表示に使うメソッドをShapeに持たせるのはおかしい その場合はどこか別
- 366 名前:で限定的にこのパターンマッチを使えばいいのではないか? []
- [ここ壊れてます]
- 367 名前:デフォルトの名無しさん mailto:sage [2016/08/27(土) 19:54:53.32 ID:vp5ltHnS.net]
- 相性が悪いわけではなく、用途がないんだと思う。
型ありOOPの場合は、型判定+分岐を仮想関数で対応するのが基本思想である為、 そもそもの例がswitch文で型判定の時点で要らない子でしかない。 もうちょっとマシな例はなかったのかよ、とも思うが。 つかどっちかというと、 パターンマッチングが活躍している言語のソースを眺めた方が良いのではないか? 誰か知ってたら教えてプリーズ。
- 368 名前:デフォルトの名無しさん mailto:sage [2016/08/27(土) 20:00:45.28 ID:vp5ltHnS.net]
- あ、ただ、絞り込みは出来るようだから、それは役に立つか?
> case Rectangle s when (s.Length == s.Height): > case Rectangle r: もちろんメソッドでも出来るが、色々まどろっこしくなるのかも。 (俺はC#erではないので詳しくは分からない)
- 369 名前:デフォルトの名無しさん mailto:sage [2016/08/27(土) 20:33:04.97 ID:vp5ltHnS.net]
- >>352
> GUI側で図形の表示に使うメソッドをShapeに持たせるのはおかしい 言っていることは分かるけども、それは思想によると思うよ。 OOP原理主義だとして、GUI側からの描画リクエスト対応もメソッドとして持たせた場合、 オブジェクトのメソッドは永遠に追加されていくことになるので、オブジェクトのソースが確定しない。 でも、OOPの基本理念、「動作しているコードには一切触れることなく機能追加可能」は実現出来る。 したがって、デグレードの危険が全くない。 機能の切り分けとしてはGUI側に持たせたいところだけど、 これだと追加Shape毎にGUI側もいちいち対応しないといけなくなる。 (動いているコードを修正する必要がある) オブジェクトが肥大化するけども、 バグを出さない為の管理なら、オブジェクト側に持たせた方が楽だと思う。 他プログラムとオブジェクトを共用する気なら、 オレオレメソッドで肥大化したオブジェクトなんて要らないから、 GUI側に持たせることになる。 もしかして拡張メソッドってこのため?アレいまいちピンとこなかったんだが。
- 370 名前:デフォルトの名無しさん mailto:sage [2016/08/27(土) 21:12:00.13 ID:n0Zp8t3m.net]
- Shapeのコンテキストによるだろ
数学や物理の計算に使うモデルなら描画用メソッドなんて書いた時点で解雇されるし 描画モデルなら描画用メソッドがあってもいい
- 371 名前:デフォルトの名無しさん mailto:sage [2016/08/27(土) 21:43:02.69 ID:vp5ltHnS.net]
- だからそのための拡張メソッドじゃないの?
今回の例なら、GUI側で拡張メソッドを追加して対応する。 すると、既存コードに手を加えることもなく、描画部分もswitch文無しという、両取りが可能。 追加Shapeがあった時もGUI側の拡張メソッド部分に追加するだけ。管理もしやすい。 https://msdn.microsoft.com/ja-jp/library/bb383977.aspx
- 372 名前:デフォルトの名無しさん mailto:sage [2016/08/27(土) 22:01:19.98 ID:gXVhUUHW.net]
- >>357
それは詭弁だな 拡張メソッドは単に型ごとにGetAreaをオーバーロードしてるだけだ オブジェクト指向というよりはむしろ関数型的なやり方 型switchや仮想メソッドは実行時型に応じた動的な多相を実現する手段で、拡張メソッドで代替できるものではないよ
- 373 名前:デフォルトの名無しさん mailto:sage [2016/08/27(土) 22:23:19.62 ID:E9zwljSJ.net]
- >>357
今の流れに拡張メソッド全く関係ないよね
- 374 名前:デフォルトの名無しさん mailto:sage [2016/08/27(土) 22:23:59.95 ID:vp5ltHnS.net]
- >>358
> 実行時型に応じた動的な多相 C#には無いだろこれ。
- 375 名前:デフォルトの名無しさん mailto:sage [2016/08/27(土) 22:37:21.41 ID:gXVhUUHW.net]
- >>360
? 普通にメソッドのオーバーライドによる多態のことだよ
- 376 名前:デフォルトの名無しさん mailto:sage [2016/08/27(土) 22:42:35.41 ID:vp5ltHnS.net]
- >>361
例えばJavaScriptでは動的に型を変更出来る。 だから実行時にswitchでやるのとコンパイル時に静的にリンクするのでは動作が異なってくる。 そういうのはC#にはないでしょ、って話。 だから話を戻すと、>>329のケースは通常のOOPの多態、 >>352のケースは拡張メソッドが一番良いと思う。 本家のも普通はOOPで対応する。 ただそれだと例にならないのでクエリがわざわざくっつけられているのだと思う。
- 377 名前:デフォルトの名無しさん mailto:sage [2016/08/27(土) 22:43:28.66 ID:yK/3tXKV.net]
- 何の話を
- 378 名前:してるのかなってちょっと上からレス読んでみたけど、
>>352の話ならShapeがDrawを持っても別に必ずしもおかしくないし、 持たせたくないならShapeで描画側が要求する描画に必要なデータを提供する 一連のメソッドやプロパティを定義しておけば済む話だよね。 描画側で型を見て分岐なんてどう贔屓目に見ても最悪のやり方にしか思えんね俺も。 [] - [ここ壊れてます]
- 379 名前:デフォルトの名無しさん mailto:sage [2016/08/27(土) 23:01:52.80 ID:gXVhUUHW.net]
- >>362
最初の4行は俺にはよく意味がわからないけどそれはまあいいとして、 >>329で多態が必要なのに>>352は拡張メソッドでいいというのは矛盾してるよ。 List<Shape>に入ってるものを全部Drawしたいとき、型ごとの拡張メソッドじゃ対応できないよ? Shapeの外部にメソッドを定義しつつ多態相当の動作をさせたい、そのうえ明示的な型判定はダメというんなら、 引数をdynamicにキャストして強引に動的ディスパッチさせるみたいなことが必要。
- 380 名前:デフォルトの名無しさん mailto:sage [2016/08/27(土) 23:02:26.56 ID:ygls7M0s.net]
- >>363
おかしいかおかしくないかは場合による このShapeが幾何学計算ライブラリのShapeだったらDrawはおかしい 図形描画用のライブラリならDrawがあってもおかしくないしなくてもおかしくない
- 381 名前:デフォルトの名無しさん mailto:sage [2016/08/27(土) 23:10:16.02 ID:vp5ltHnS.net]
- >>364
> List<Shape>に入ってるものを全部Drawしたいとき、型ごとの拡張メソッドじゃ対応できないよ? 出来るよ。というかそちららの認識が間違っていると思うが、 拡張メソッドはソース上では普通のメソッドと見た目は同じだよ。
- 382 名前:デフォルトの名無しさん mailto:sage [2016/08/27(土) 23:15:37.10 ID:ygls7M0s.net]
- >>366
ネタかマジかからかってるかわからないんだけど
- 383 名前:デフォルトの名無しさん mailto:sage [2016/08/27(土) 23:18:51.07 ID:gXVhUUHW.net]
- >>366
ほんとに? https://ideone.com/lmc8TO たまには自分の思い込みを疑ってみるのも大切だぞ
- 384 名前:デフォルトの名無しさん mailto:sage [2016/08/27(土) 23:19:50.69 ID:vp5ltHnS.net]
- >>364
>>367 いやこちらも意味不明なのだが。 逆に>>364の言う「メソッドでは対応出来るが拡張メソッドでは対応出来ない」ケースって出せるか?
- 385 名前:デフォルトの名無しさん mailto:sage [2016/08/27(土) 23:28:42.22 ID:vp5ltHnS.net]
- >>368
いやそれOOPじゃないと思うが、、、ただのオーバーロードだよね。
- 386 名前:デフォルトの名無しさん mailto:sage [2016/08/27(土) 23:31:52.50 ID:gXVhUUHW.net]
- >>370
だから俺は>>358からそう言ってるじゃん 拡張メソッドでは対応できないケースを示しただろ?
- 387 名前:デフォルトの名無しさん mailto:sage [2016/08/27(土) 23:33:00.29 ID:ygls7M0s.net]
- >>369
拡張メソッドにできない事、のシンプルな答えとして挙げるなら、インスタンスメソッドにはなれない、だな それでもう終わりだろこの話 わからないなら入門書読み直してくれ
- 388 名前:デフォルトの名無しさん mailto:sage [2016/08/27(土) 23:40:42.34 ID:vp5ltHnS.net]
- >>371,372
まあ俺はC#erではないので拡張メソッドは使ったことがないし、 俺の理解が間違っている可能性もあるが、 MSDNの仕様書を見る限り、当たり前だがメソッドを拡張したように見せかけているのだと思うよ。 だからその場合は Rectangle と Circle に対して拡張メソッドを追加する。 これができないのならそちらの言うとおりだが、それだと拡張メソッドなんてゴミじゃん。 まあどのみち俺かそちらの仕様に対する勘違いだと思うので、この話はこれで終わりでいい。
- 389 名前:デフォルトの名無しさん mailto:sage [2016/08/27(土) 23:48:05.17 ID:vp5ltHnS.net]
- >>372
いや悪いがやっぱりそっちが間違ってるぞ。 拡張メソッドで普通にthisが取れてる。(引数の所に書く) つかそうじゃないと意味無いだろ。 > public static int WordCount(this String str) > { > return str.Split(new char[] { ' ', '.', '?' }, > StringSplitOptions.RemoveEmptyEntries).Length; > } > https://msdn.microsoft.com/ja-jp/library/bb383977.aspx
- 390 名前:デフォルトの名無しさん mailto:sage [2016/08/28(日) 00:08:50.44 ID:s1SxoEZK.net]
- >>374
あんたにも分かるように説明してあげよう 拡張メソッドとは、HogeClass.func(x) を x.func() と書けるシンタックスシュガーである そ れ だ け
- 391 名前:デフォルトの名無しさん mailto:sage [2016/08/28(日) 00:15:50.55 ID:zGC1w6Ia.net]
- >>365
だからそう言ってるでしょ。
- 392 名前:デフォルトの名無しさん mailto:sage [2016/08/28(日) 00:17:10.42 ID:+mkoP4gZ.net]
- >>375
それはオブジェクト指向がその意味でのシンタックスシュガーでしかないよ。 class構文が無かったCでも関数ポインタ+構造体で同じ事が出来たわけだし。 重要なのは拡張メソッドにthisが渡っていることだよ。 静的メソッド(クラスメソッド)にはthis使えないでしょ。 今回の例で言えば、宣言部分は以下になるということ。 ただしコンパイルが通るかどうかは知らんが。 通らないのなら君の言うとおり、通るのなら俺の言い分が正しいことになる。 public static void Draw(this Rectangle rect) public static void Draw(this Circle circle)
- 393 名前:デフォルトの名無しさん mailto:sage [2016/08/28(日) 00:19:39.62 ID:UJTSRlJK.net]
- 何で拡張メソッドってstaticクラスじゃないと定義出来ないんだ?
何か理由あるの? 別に制限はstaticメソッドだけでいいと思うけど 例えばString.IsNullOrEmpty(String) もしstaticクラス以外に拡張メソッド定義出来たら String.IsNullOrEmpty(this String) みたいになって更に便利になると思うのに
- 394 名前:デフォルトの名無しさん mailto:sage [2016/08/28(日) 00:21:24.05 ID:hQF+q+Zk.net]
- そこのthisは単に拡張メソッドのマーク
通常のthisとは違う意味 拡張メソッドは親クラスからは呼べないからそれを定義してもShapeクラスから直接呼べない RectangleやCircleにキャストすることになる そこで登場するのがパターンマッチングと
- 395 名前:デフォルトの名無しさん mailto:sage [2016/08/28(日) 00:26:26.11 ID:UJTSRlJK.net]
- 今更変えるのは互換性的な問題で難しいだろうけど、
==演算子を等価演算子 ===演算子を等値or不変インスタンスかつ等価演算子 にするべきだと思った 不変かは属性とかで定義して Equalsメソッドとかいらねーだろ ==演算子と両方定義しろとかどうなってんだ
- 396 名前:デフォルトの名無しさん mailto:sage [2016/08/28(日) 00:31:26.64 ID:+mkoP4gZ.net]
- >>379
いや拡張メソッド内で自分自身のメンバを参照出来るよ。多分。 > 実際に、拡張メソッドは、それらが拡張している型のプライベート変数にはアクセスできません。 > https://msdn.microsoft.com/ja-jp/library/bb383977.aspx 普通に考えれば、わざわざプライベートは駄目って書いてある時点でpublicならいけるって事でしょ。 要するに外面的には Draw(circle) でしかないところを circle.Draw() と書けるだけでしかない。 その辻褄はコンパイラが合わせるけど、privateをpublicには出来ないのでこれは無理。 MSDNの説明には矛盾を感じないけど。
- 397 名前:デフォルトの名無しさん mailto:sage [2016/08/28(日) 00:36:48.79 ID:+mkoP4gZ.net]
- >>379
> 拡張メソッドは親クラスからは呼べないからそれを定義してもShapeクラスから直接呼べない バインディングはコンパイル時だし、多分普通に呼べると思うよ。 というか呼べないと拡張にならないから、文法が違ったとしても何らかの呼び方は必ずあるはず。
- 398 名前:デフォルトの名無しさん mailto:sage [2016/08/28(日) 00:37:11.60 ID:zGC1w6Ia.net]
- >>380
EquqlsというかIEquatableが不要とは思わないけど、 VBと同じように参照等価検査専用の演算子を用意して、==はオーバーロードしないと 使えないようにしてくれた方が分かりやすかったね。
- 399 名前:デフォルトの名無しさん mailto:sage [2016/08/28(日) 00:43:30.59 ID:hQF+q+Zk.net]
- >>379
RectangleとCircleにDraw拡張メソッドが定義されているなら以下のようになる void hoge( Shape shape ) { //できない //shape.Draw(); if(shape is Rectangle)((Rectangle)shape).Draw(); else if(shape is Circle)((Circle)shape).Draw(); } 拡張メソッドを呼び出すときにキャスト必須 「Shapeを継承したクラスはすべてDraw拡張メソッドを定義しなければならない」 という条件はかなり強引で、ヘタすればCLRや共通言語仕様にも手を入れなければいけない問題になる
- 400 名前:デフォルトの名無しさん mailto:sage [2016/08/28(日) 00:45:09.67 ID:s1SxoEZK.net]
- >>378
スコープが広がってルールが複雑になるから 例えばこういうときどうする? /* ファイル1.cs */ namespace NS1 { class Hoge { public static void EX(this Hoge h) { … } } /* ファイル2.cs */ namespace NS2 { class Test { public static void Main() { new NS1.Hoge().EX(); } } } これ、現在の仕様から類推すればファイル2内ではNS1をusingしてないから EXは拡張メソッドとして呼び出せないはずだけど、直感的には呼べた方が自然だと思わない? それとか、拡張メソッドを含むクラスを別の名前空間のクラスが継承したらどうする?
- 401 名前:デフォルトの名無しさん mailto:sage [2016/08/28(日) 00:59:15.28 ID:hQF+q+Zk.net]
- >>382
拡張メソッドはコンパイラで解決しなきゃいけない しかし、外部のDLLがShapeの子クラスを実装して、それを動的に読み込む可能性があるのでコンパイラでは解決不能 >オブジェクト指向がその意味でのシンタックスシュガーでしかないよ そういうことを言ってるんじゃない オブジェクト指向は共通言語仕様に書かれているのでILにその情報が残り、すべての言語が対応する それに対しシンタックスシュガーはコンパイラの機能でILに完全には残らなかったり、属性をつけることで対応しているコンパイラのみが利用する
- 402 名前:デフォルトの名無しさん mailto:sage [2016/08/28(日) 01:12:12.64 ID:+mkoP4gZ.net]
- >>386
コンパイラ云々は俺は普通に出来ると思っているのだが、まあそれは置いておこう。 >>384 こちらを先にやろう。 > //できない > //shape.Draw(); これって出来ないんだっけ?というかこちらは最近はJavaScript(型無し)でやっていて、 void hoge(var shape ) // var なので何でも入る { shape.Draw(); // 勝手に直近のvirtualが呼ばれる。 } で普通にオーバーライドされたvirtualが呼べる(circle.drawなりrectangle.drawなり)から、 実際のC#での記述の仕方は知らない。 ただ、アップキャストしたらもう仮想関数は呼べません、ダウンキャストしてからにしてください、 だとOOPとしてはかなり無理があるから、自然なやり方がないわけ無いと思うけど。 だってその is 構文ってのも新しいんでしょ? だったらそれがなかったこれまではOOPできませんでしたーってことになっちゃうじゃん。
- 403 名前:デフォルトの名無しさん mailto:sage [2016/08/28(日) 01:32:13.31 ID:hcj7YQtW.net]
- しつけえなあ
入門書ぐらい読んでからにしろよ なんでど素人がそんな自信満々なんだよ
- 404 名前:デフォルトの名無しさん mailto:sage [2016/08/28(日) 01:33:21.98 ID:+mkoP4gZ.net]
- >>384
以下見る限り、virtual付けたら普通にOOPできるとしか読めないが。 てか当たり前だが。 引き数渡ししたら出来なくなるって事もないと思うけど。 > しかし、動的な型に基づいて呼び出されるメソッドを決定したい場合があります。 > (というより、ほとんどの場合、メソッド呼び出しは動的に決定した方が都合がいい。) > 動的な型に基づいて呼び出されるメソッドを選びたい場合、 > 以下のように、 メソッドに virtual という修飾子を付けます。 > ufcpp.net/study/csharp/oo_polymorphism.html その上にvirtual付けなかった場合も書いてあるから見比べれば分かると思うよ。
- 405 名前:デフォルトの名無しさん mailto:sage [2016/08/28(日) 01:37:09.54 ID:+mkoP4gZ.net]
- >>388
まあその通りだ。今は最新環境がないので試せない。 確かにこれ以上やっても意味無いので、後日最新環境で試せば良いだけだね。 「拡張メソッド」ってのに俺が夢を見すぎているのかもしれんし。
- 406 名前:デフォルトの名無しさん mailto:sage [2016/08/28(日) 02:08:02.18 ID:hQF+q+Zk.net]
- >>389
何度も行っているように、拡張メソッドではオーバーライドできない。 なぜなら拡張メソッドはただのC#限定のstaticメソッドのシンタックスシュガーに過ぎないから。 そのURLではどこにも拡張メソッドのことは書いてないでしょ class Triangle : Shape{} ってプラグインみたいに外部のDLLで宣言されて、それを動的に読み込んで、hogeに渡ってきたらどうするの? 外部のDLLのことなんてコンパイルの地点では知らないので存在しない拡張メソッドを呼べるはずがない。 夢を見すぎているんじゃなくて、ただ無知でC#とかCLIをよく理解してないだけだと思う javascriptで言うならprototypeの存在も知らないでjavascriptはウンタラカンタラ言っている状態なので、基礎から学び直したほうがいい
- 407 名前:デフォルトの名無しさん mailto:sage [2016/08/28(日) 08:45:51.40 ID:UJTSRlJK.net]
- >>385
そういう事か…確かに面倒だな それならnull可メソッド的な物を作ればいいんじゃない public null void Hoge(){ //thisがnullの可能性あり }
- 408 名前:デフォルトの名無しさん mailto:sage [2016/08/28(日) 09:58:20.62 ID:+mkoP4gZ.net]
- >>391
試したぞ。VS
- 409 名前:Community2015はサインインしないと使えなかったから、VS2008EEだが。
その範囲では確かに出来なかった。コードは以下ページを参考に改変した。 > http://ichitcltk.hustle.ne.jp/gudon2/index.php?pageType=file&id=cs002_ExtensionMethods しかし理由は拡張メソッドがstaticだからだよ。以下コードで、 class SampleClass1 {} class SubClass : SampleClass1 {} static class hoo { static public void SampleExtensionMethod1(this SampleClass1 sampleClass1) { Console.WriteLine("super_ex"); } static public void SampleExtensionMethod2(this SampleClass1 sampleClass1) { Console.WriteLine("super_ex2"); } static public void SampleExtensionMethod1(this SubClass subClass) { Console.WriteLine("sub_ex"); } } static void test(SampleClass1 sampleClass1) { sampleClass1.SampleExtensionMethod1(); // (A) sampleClass1.SampleMethod1(); // (B) } static void test3(SubClass subClass) { subClass.SampleExtensionMethod2(); .// (C) } [] - [ここ壊れてます]
- 410 名前:デフォルトの名無しさん mailto:sage [2016/08/28(日) 09:59:05.95 ID:+mkoP4gZ.net]
- (B)は通常メソッドで、SubClassが与えられると当然SubClassのメソッドが呼ばれる。
ただし(A)は常にSampleClass1(親クラスというより「そこに記述された」クラス)の拡張メソッドが呼ばれる。 なお(C)はSampleClass1の拡張メソッドが呼ばれる。 (つまり子→親に関しては辿れる) (B)が動作する以上、thisポインタは正しく渡っている。 あとは拡張メソッド側に継承関係を明記し、実行時型でこれを解決すれば良いだけなのだけど、 C#はどうやら文法的にこれを禁止している。(技術的には全く問題なく出来るはず) 今回出来ないのは、拡張メソッドがstaticだからコンパイル時にそこにリンクされるからだ。 そこでvirtual指定してみたが、これはSyntacErrorで落ちる。 どうやらそれ以前にC#は静的クラスは継承禁止で、当然virtualには出来ない。 しかしそもそも静的クラスが継承出来ないのが問題だ。 何故これを禁止しなければならないのかは分からない。 結局>>378の「static縛り」或いは上記「staticクラスは継承出来ない」のが問題。 とはいえこの仕様では「拡張メソッド」がイマイチなのはC#開発側も認識出来るだろうから、 何らかの理由があってこの仕様なのだとは思うが。 したがって>>364の指摘どおり、 > >>329で多態が必要なのに>>352は拡張メソッドでいいというのは矛盾してるよ。 これは間違いだった。拡張メソッドが多態出来ないのは知らなかったから。 となると>>352は ・Shapeクラスにメソッド追加---(α) ・GUI側でShapeクラスを継承したクラスを作って対応---(β) ・>>384方式で is XXXX 形式で全部書く---(γ) のどれかになるが、俺ならαかβであって、γはないね。
- 411 名前:デフォルトの名無しさん mailto:sage [2016/08/28(日) 10:08:01.32 ID:acJIbkh4.net]
- スクリプトコーダーらしいパフォーマンス無視の考え嫌いじゃないよ
- 412 名前:デフォルトの名無しさん mailto:sage [2016/08/28(日) 10:18:04.05 ID:+mkoP4gZ.net]
- 釣りか?
仮想関数とif/switch分岐でのコストはC++の連中が死ぬほど議論しているが、 結論はどっちもほぼ同じだよ。 だからαもβもγも動作速度は大して変わらないはずだけど。 しかしそもそもC#ってパフォーマンス重視出来る言語じゃないよね。
- 413 名前:デフォルトの名無しさん mailto:sage [2016/08/28(日) 10:21:51.48 ID:acJIbkh4.net]
- >>396
そこじゃない
- 414 名前:デフォルトの名無しさん mailto:sage [2016/08/28(日) 10:24:49.86 ID:+mkoP4gZ.net]
- じゃあどこだよ?
てかチャットじゃねーんだから意見があるのなら分かるように書けよ
- 415 名前:デフォルトの名無しさん mailto:sage [2016/08/28(日) 10:26:20.15 ID:acJIbkh4.net]
- >>398
それ君が言うんだ?
- 416 名前:デフォルトの名無しさん mailto:sage [2016/08/28(日) 10:32:20.35 ID:1sBWhH04.net]
- >>396
>C#ってパフォーマンス重視出来る言語じゃないよね これ免罪符に糞コード生み出す奴多いから困る
- 417 名前:デフォルトの名無しさん mailto:sage [2016/08/28(日) 10:34:33.21 ID:acJIbkh4.net]
- 入門書も読まないスクリプトコーダーはdynamicでも使ってろってこった
- 418 名前:デフォルトの名無しさん mailto:sage [2016/08/28(日) 11:04:12.58 ID:h1JFz9az.net]
- ウザイから質問者と回答者以外が3行以上書いたら死刑な
- 419 名前:デフォルトの名無しさん mailto:sage [2016/08/28(日) 12:58:05.84 ID:0rJ/vUpY.net]
- ひょっとして結局拡張メソッドからは型の外のスコープからアクセスできるメンバーにしか
アクセスできない、っていう糞当たり前の話を延々やってだけなの? そんなのちょっと我慢して拡張メソッドの解説記事を5分も読んだら猿でも分かる話だろw
- 420 名前:デフォルトの名無しさん mailto:sage [2016/08/28(日) 13:59:05.59 ID:ZfPDxmLp.net]
- フロントエンドコーダーってろくな人材いないよな
- 421 名前:デフォルトの名無しさん mailto:sage [2016/08/28(日) 14:35:00.94 ID:hQF+q+Zk.net]
- >>394
実行時に解決するのは非常にコストが高い。 多分仮想関数を理解してないんだと思うけど、静的メソッドはC++やC#の方式だと仮想関数テーブルに無いので仮想関数になり得ない また、呼び出しに失敗する可能性があるというリスクがあり、静的型付け言語の良さを殺している >そもそもC#ってパフォーマンス重視出来る言語じゃないよね。 大きな勘違い。Roslynとかではパフォーマンスをかなり重視してる。 実行時はネイティブコードになるので書き方によってはC++と同等の速度が出る。 (ただし、C++は危険な操作を行ったりできるのでその分有利) >staticクラスは継承出来ない なぜなら、staticクラスは「インスタンス化、継承できない」という指定付きのクラスだから。なぜintは数値しか表せないのかみたいな意味不明な主張 >・Shapeクラスにメソッド追加---(α) Shapeクラスが汎用的に使ったり、ライブラリとして公開するクラスならどうしようもない WPF、WinForms、Xamarinなど、プラットフォームによって描画方法は全然異なるのでDrawメソッドを決められない >・GUI側でShapeクラスを継承したクラスを作って対応---(β) 手間が掛かり過ぎるし、構造体やsealedクラスなら継承はできない。 クラス内にフィールドで保持してもいいが、Int32WrapperとかStringWrapper、加えて列挙体や関数、タプルなんかのラッパークラスができて複雑に。 状況によってはInt32WrapperWrapperみたいなものも爆誕
- 422 名前:デフォルトの名無しさん mailto:sage [2016/08/28(日) 14:43:51.29 ID:hQF+q+Zk.net]
- 普通にココらへんのリンクで十分か
www.buildinsider.net/column/iwanaga-nobuyuki/004 >GUI側でShapeクラスを継承したクラスを作って対応 これは構文解析ライブラリは継承前のクラスを返してくるわけだから、無理があった
- 423 名前:デフォルトの名無しさん mailto:sage [2016/08/28(日) 14:55:35.63 ID:14dFRx50.net]
- 拡張メソッドで話がだいぶ逸れたけどなに話してたんだっけ
- 424 名前:デフォルトの名無しさん mailto:sage [2016/08/28(日) 14:56:21.93 ID:QOlzH7cc.net]
- できない君か
- 425 名前:デフォルトの名無しさん mailto:sage [2016/08/28(日) 15:27:24.87 ID:+mkoP4gZ.net]
- >>405
先に了解事項を書いておく。 > >staticクラスは継承出来ない > なぜなら、それが定義だから(意訳) これは了解。こちらも調べている限り、どうやらそのようだと分かった。 staticクラスはシングルトンの糖衣かと思っていたが、わざわざ別物を用意しているね。 > 静的クラスはシールされるため、継承できません。 > https://msdn.microsoft.com/ja-jp/library/79b3xss3.aspx > staticクラスとSingletonでは以下の違いがあります。 > takachan.hatenablog.com/entry/2016/01/04/211414 したがって、疑問は何故staticクラスにしか拡張メソッドを置けないか、になり、 つまり>>378と同じで、そちらの見解は>>385というのもいい。 ただ俺はこの回答に納得しているわけではないが、 結局これはどこまでやるかということだから。
- 426 名前:デフォルトの名無しさん mailto:sage [2016/08/28(日) 15:30:05.25 ID:+mkoP4gZ.net]
- 次に今回の実装方式について、
(α)についてはその通り。 (β)については「継承」が出来ればそっちの方がいいが、無理なら「内包」でも問題ない。(β+) コンストラクタでShapeを与えて内包したRectangleDraw、CircleDrawクラスを作り、 ShapeDrawクラスを継承する。 つまりラッパーオブジェクトを作成して同階層構成でXXXXDrawクラスを構成する。 これだと自前クラスなので何も問題なくOOPできるが、 コンストラクタ内では1回だけ is XXXX でswitchしなければならない。 それでも毎回記述が必要な(γ)よりマシ。 > クラス内にフィールドで保持してもいいが 後の文を読む限りこれはばらしてということだと思うが、 (β+)はばらさすにそのまま保持する。(フィールドとして Shape shapeを持つ) そして各Drawメソッドからは this.shape.xxxxとしてアクセスする。 こうすれば、アクセサに関してもShapeの定義そのままであり、追加記述は必要ない。 これにより、外枠以外の本質的記述が(γ)に対して増えることはない。 これでどうだ? 最後に以下だが、 > 実行時に解決するのは非常にコストが高い。 > 多分仮想関数を理解してないんだと思うけど、静的メソッドはC++やC#の方式だと仮想関数テーブルに無いので仮想関数になり得ない > また、呼び出しに失敗する可能性があるというリスクがあり、静的型付け言語の良さを殺している これはいろいろだいぶ違う気がするが、確認も時間がかかるし、後回しでいい。
- 427 名前:デフォルトの名無しさん mailto:sage [2016/08/28(日) 15:40:18.87 ID:xWdxGs/J.net]
- パターンマッチング推進派の巧妙なアンチ書き込みか!
- 428 名前:デフォルトの名無しさん mailto:sage [2016/08/28(日) 15:50:02.41 ID:+mkoP4gZ.net]
- >>406
リンク先読んだ。筆者の考え方とは同意する。 結果、俺は以下に該当するのでオブジェクト側に突っ込みたいと考える。 > 型だけを見た単純な分岐しかしない場合、 > 仮想関数を使う方が実行性能面でも保守しやすさの面でもいいだろう。 そちらは以下に該当すると考えてパターンマッチングというのも了解だ。 > 1つは、型の外に実装を書く方が好ましい場合だ。(中略) > 特定の種類のアプリでしか使わないような機能を書く場所としては (型は)【追補】 > 不適切となる。
- 429 名前:デフォルトの名無しさん mailto:sage [2016/08/28(日) 16:06:33.60 ID:+mkoP4gZ.net]
- >>405
ちなみに以下について俺の疑問点を先に挙げておく。 > 実行時に解決するのは非常にコストが高い。 > 多分仮想関数を理解してないんだと思うけど、静的メソッドはC++やC#の方式だと仮想関数テーブルに無いので仮想関数になり得ない > また、呼び出しに失敗する可能性があるというリスクがあり、静的型付け言語の良さを殺している ・静的メソッドはvtableに置く必要はないが、普通はそこに置いているはず。 それが一番簡単だし。 (クラス自体がstaticではないのでコンパイル時にリンクは無理) したがって、virtualメソッドとstaticメソッドの実行速度差は無いはず。 ・呼び出しに失敗って何?C#ならコンパイルが通っている限りあり得ないと思うが。 (C++みたいな<reinterpret_cast>とかは無しで) ・実行時に解決って言ったって、vtableの場合は解決済みのthisポインタを持っているわけであって、 何かを比較したりすることはない。間接呼び出しになるだけ。 コストはゼロではないが、リフレクションとかとは全く違う。 URL付きのツッコミは歓迎。
- 430 名前:デフォルトの名無しさん mailto:sage [2016/08/28(日) 16:30:05.10 ID:+mkoP4gZ.net]
- 追記
俺の間違いが分かったので書いとく。 × > ・静的メソッドはvtableに置く必要はないが、普通はそこに置いているはず。(>>413) ○ 置いてない。静的メソッドは直接呼び出し。 × > したがって、virtualメソッドとstaticメソッドの実行速度差は無いはず。 ○ 直接呼び出しする非virtualの方がvirtualよりは速い。 staticメソッドには言及されていないが、多分非virtualと同じ。 > メンバ関数 > https://www.microsoft.com/japan/msdn/vs_previous/visualc/techmat/feature/jangrayhood/ 他の下2件はどこを調べればいいか分からないのでツッコミ待ち。 よろしく。
- 431 名前:デフォルトの名無しさん mailto:sage [2016/08/28(日) 18:36:26.78 ID:hQF+q+Zk.net]
- >>410
>1回だけ is XXXX でswitchしなければならない その時にパターンマッチング使えば楽だよねって話でしょ 毎回使うかどうかは好みや書き方次第かと >呼び出しに失敗 拡張メソッドの実装を理解してる? ExtensionAttributeを静的クラスに付与して、コンパイルの時にそれを見てるだけ。 https://msdn.microsoft.com/ja-jp/library/system.runtime.compilerservices.extensionattribute%28v=vs.110%29.aspx?f=255&MSPPError=-2147217396 継承関係とは違って共通言語仕様に定められていない(はず)なので、全言語が対応していない 例えばShapeクラスとかをライブラリとして公開したとすると、他の言語がShapeクラスを継承した時に必ず拡張メソッドを書いてくれることは保証できない そうすると、存在しないメソッドは呼び出せないので失敗することになる 何なら、動的に新しい型自体を作成してメソッドに渡すことすらできる。 >実行時に解決 拡張メソッドはそもそもサポートしてない言語もあるし、全く独立したクラスなのでそもそも動的に解決するのが困難 やろうとすればたぶん共通言語仕様とかの変更が必要で影響ばかりでかくて利点が皆無
- 432 名前:デフォルトの名無しさん mailto:sage [2016/08/28(日) 19:17:00.51 ID:+mkoP4gZ.net]
- >>415
いや>>352に対する君の主張は「毎回べた書き」だろ。すり替えるなよ。 それはさておき、通常はクエリメソッドを用意しておいてそれで対応だ。 例えば Shape.type で 'rectangle' や 'circle' が取れるとか。 だからパターンマッチング自体の記述は要らんよ。(見た目は同様ではあるが) というかそれが絶対に必要ならこれまでどうしようもなかったことになっちゃうだろ。 > ExtensionAttributeを静的クラスに付与して、コンパイルの時にそれを見てるだけ。(中略) > そうすると、存在しないメソッドは呼び出せないので失敗することになる だから何?コンパイラが通らないだけだろ。 話がずれているか? 上記話のすり替えをしてくる奴だから信用はしていないが。 >>405を見る限りこちらは「一般」の仮想関数だと認識して回答した。(>>413,414) そちらは ・「拡張メソッド」の動的解決はコストが高くて、仮想関数になりえなくて、呼び出しに失敗する ことを言っていたか? それなら「一般メソッド」について記述した>>413,414については見解の相違なしということでいいな。 > 他の言語がShapeクラスを継承した時に必ず拡張メソッドを書いてくれることは保証できない 当たり前。というか静的にリンクするんだから、namespaceに名前がない時点でコンパイルが通らないだけ。 使う気なら自前で定義なりusingしなければならないし、無ければ使えない。 多態する気なら、例えば多重継承として実装すればいいだけ。特別なコストはかからない。 実装方式は>>414のリンクに記述してあるとおり。 拡張メソッドを多重継承として実装出来ない理由があるか? > 利点が皆無 どこがだよ?やけくそになってないか? 拡張メソッドが多態出来ればメリットがあるのは見たら分かるだろ。 今多態出来ていないのは何か理由があるか手を抜いているか(今後対応するか)だよ。
- 433 名前:デフォルトの名無しさん mailto:sage [2016/08/28(日) 19:49:44.91 ID:hQF+q+Zk.net]
- >>416
>毎回べた書き その主張は俺じゃないが? >クエリメソッド 何を言っているんだ?今でもできるぞ?? if( hoge is Rectangle){ ((Rectangle)hoge).Draw(); } とか。状況によってもっとわかりにくくなるから、もっと簡潔に書きたいね、という話なんですが・・・ 流石に語るのにC#を知らなすぎじゃないか? >静的にリンクする 静的にリンクしないこともある。わざわざプラグインとかDLLとか言ってるでしょ? C#では言語仕様上、コンパイル時に継承した型をすべて把握できない あと、「他言語は対応していない」の部分を完全に無視してるみたいだけど、そこも要点なんですが >「一般メソッド」について記述した>>413,414については見解の相違なし 訂正が入って主張がわかりにくくなってるが、一般メソッドに関しては問題ないと思われる 拡張メソッドはC#の言語仕様ではなくて共通言語仕様の方で対応してないので、同じ仕組を実現できない >多重継承 全く独立したクラスのstaticメソッドをどうやって多重継承するの? >拡張メソッドが多態出来ればメリットがあるのは見たら分かるだろ ほぼ拡張メソッドじゃなくてさっき君が言ったShapeDrawクラスを使うべき案件 僅かにメリットがあっても、共通言語仕様を置き換えて、多言語のコンパイラ(VB.NET,F#,C++/CLI,JScript.NET等)を書き換え、UnityやMono、Xamarinを対応させ、後方互換を除去してまで導入する機能かというとそうは見えないな .NET Frameworkが始まる前とかに提案すればよかったかもしれんが 本気で完璧な利点があると思うなら、Roslynにissueを立てると良い
- 434 名前:デフォルトの名無しさん mailto:sage [2016/08/28(日) 20:04:28.22 ID:hQF+q+Zk.net]
- >Shape.type で 'rectangle' や 'circle' が取れるとか。
ちなみに、これは一番危険 標準ライブラリにあるShapeクラスをA社とB社が継承し、AライブラリとBライブラリを作ったとする。 そのどちらのライブラリも必要だったので同時に使おうとすると、rectangleの名前が衝突して区別できない!となる。 そこで使うのが「型」なわけだ。 現在でも出来てるけど、コンパイラ制作とかだと頻繁に出てくるよね〜、なら、パターンマッチング導入しよう!という流れかと。 ちなみに、ShapeDrawクラス見たいのにも問題はあって、例えば構文解析した要素が10000を超える巨大な木構造があるとする。 それをGUI側ですべてNodeDrawみたいなクラスにラップするとその変換にかかる時間とメモリが馬
- 435 名前:ュにならなくなってくる
さらに、ライブラリの木構造が変更されると、GUI側ではすべて構築しなおし 手間を防ぐためにキャッシュしたり差分のみを変更して・・・という状況になる場合もある [] - [ここ壊れてます]
- 436 名前:デフォルトの名無しさん mailto:sage [2016/08/28(日) 20:23:46.58 ID:5A6j7Ufp.net]
- なんでこんな荒ぶってんのこいつ
とりあえず落ち着いて猫でもわかるC#でも読みなって
- 437 名前:デフォルトの名無しさん mailto:sage [2016/08/28(日) 20:23:47.93 ID:+mkoP4gZ.net]
- >>417
こちらの認識は、ID:gXVhUUHW = ID:hQF+q+Zk だ。 違っていたのならすまんかった。 > クエリメソッド クラスの中に複数種が入ることがある場合、(多態される場合) 一般的に「何が入っているか」は分かるようになっている。だからそれを使う。 C#の文法による解決は必要ない。(というかそうじゃないと動的型を取れない言語で使えない) > あと、「他言語は対応していない」の部分を完全に無視してるみたいだけど、そこも要点なんですが これについては関係ないとしか思えない。 拡張メソッドを自動的にエクスポート出来ると思っているのならそれが間違いだろ。 namespaceの中に拡張メソッドが見えていないと使えないのだから、 使う側が全部管理しないといけない。 同じ拡張メソッドを他でも使いたければ、その拡張メソッドを格納したクラスを使う側がusingしないといけない。 現在の実装はあくまで「コンパイラがstaticクラスのstaticメソッドに対しての関数呼び出し」に変更するだけ。 それがコンパイル時に出来なければコンパイルが通らない。他言語はどこに関係あるんだ? > 全く独立したクラスのstaticメソッドをどうやって多重継承するの? 多重継承は全く独立したクラスを継承することですが? 当然これをやる時はvirtualにする(今現在のC#の制限事項をはがす)のだが、ついて来れているか? 元々「継承出来ないクラス」(stat;icクラス)にしか拡張メソッドを置けないのが問題であって、 拡張メソッドをシングルトンに置ければ何も問題なくなる。 そしてそれが実現出来ない技術的障害はない、というのが俺の主張。 この辺を最初から知っていて傍観してるのが>>378だろ。 > ほぼ拡張メソッドじゃなくてさっき君が言ったShapeDrawクラスを使うべき案件 いやそっちの意見は何なんだよ? 君はパターンマッチングが一番良いと思ってるんだろ? 俺は、「拡張メソッドで多態」(α)(β)(β+)の順で検討する。 ただ第一候補が今は駄目なことを知らなかったから迷走したが。
- 438 名前:デフォルトの名無しさん mailto:sage [2016/08/28(日) 20:32:09.16 ID:+mkoP4gZ.net]
- >>418
> そのどちらのライブラリも必要だったので同時に使おうとすると、rectangleの名前が衝突して区別できない!となる。 それは最初からポインタの型が違うから区別出来るだろ。 > ちなみに、、、、以降(ry それがないように、本来は「直接クラスを拡張」(α)するなり「継承」(β)するべきだろ。 やむなく内包(β+)なりパターンマッチング(γ)になった場合は変更の影響は受けるのは当たり前。 ただ、(β+)よりも(γ)の方が記述の変更量は多いよ。 その辺はMSDNにもそのまま書いてある。 > 拡張メソッドは、一般的に、必要な場合に限り注意して実装することをお勧めします。 > クライアント コードで既存の型を拡張する必要がある場合、 > 可能であれば既存の型から派生した新しい型を作成することで行ってください。 > 詳細については、「継承 (C# プログラミング ガイド)」を参照してください。 > 拡張メソッドを使用して、変更できないソース コードのある型を拡張する場合、 > 型の実装の変更により拡張メソッドが破損するというリスクを負うことになります。 > https://msdn.microsoft.com/ja-jp/library/bb383977.aspx
- 439 名前:デフォルトの名無しさん mailto:sage [2016/08/28(日) 20:34:15.18 ID:veN4TyYm.net]
- >>420
何を言ってるのかよく分からんけどなんか盛大に勘違いしてる気がするw
- 440 名前:デフォルトの名無しさん mailto:sage [2016/08/28(日) 20:43:32.81 ID:lqCVK6M2.net]
- 彼は拡張メソッドに夢をみすぎてるんだ
現実を知らないキッズには良くあることさ 拡張メソッドで多態()
- 441 名前:デフォルトの名無しさん mailto:sage [2016/08/28(日) 20:56:44.18 ID:hQF+q+Zk.net]
- こういうサンプルで示せばいいのかな?
細かく書くと面倒なので擬似コードだけど、(拡張メソッドを通常メソッドと同様に呼び出す以外は)同じことが実際にできる https://ideone.com/hJQfol Main.exeではShapeクラスとRectクラスが定義されている。 これ単体ならすべてのShape継承クラスが拡張メソッドDrawを持ってる Main.exe用のプラグイン、plugin.dllを他の人が後から作り、Main.exeのShapeを継承したTriangleクラスを実装している。
- 442 名前:Main.exeはdllを動的に読み込み、インスタンスを作り、Hogeメソッドに渡している。
ここで、plugin.dllでは拡張メソッドDrawが定義されていない。そして、この拡張メソッドの定義を強制する手段が存在しない [] - [ここ壊れてます]
- 443 名前:デフォルトの名無しさん mailto:sage [2016/08/28(日) 21:08:44.28 ID:hQF+q+Zk.net]
- >君はパターンマッチングが一番良いと思ってるんだろ?
いや、状況次第。ラッパークラスを作るほうが良い場合も多いと思うよ。 そのラッパークラスのインスタンスを作る時にパターンマッチ構文があれば簡潔にかけるので非常にありがたい あと、今気づいたけど、そもそも構造体は仮想関数テーブル持ってないから多様性をもたせようが無かった >>394でもthisポインタって言ってるけど、構造体の場合は仕組み上コピーが渡る
- 444 名前:デフォルトの名無しさん mailto:sage [2016/08/28(日) 21:37:38.11 ID:+mkoP4gZ.net]
- >>424
それが、「コンパイルには通るが拡張メソッドを呼ぶと失敗する」例だというのなら、 言いたいことは分かった。 ただ、それは失敗して当然というか、 「知らない図が書けない」だけであって、実装してない部分が動かないだけ。 丁寧にやるのなら、拡張メソッドがない場合に□を 出力して対応するしかないし、それだけでしかない。(文字化けのようなもの) (C#に実装の有無を確認する方法があるかどうかは知らない。 JavaScriptでは問題なく出来る。 拡張メソッドが多態出来るのなら、親(Shape)に□を表示させるメソッドを実装しておく) 別にそれは正しく全てを実装する時に手間が増えるわけでもない。 dllが他言語から供給されたとしても関係ない。 そもそもそちらの言うとおりShapeが演算用クラスであった場合、 クラスを追加する側にこちら『だけ』で使っている拡張メソッドを実装してくれと言うのが無理。 拡張メソッドは使う側が全部管理しなければならないだけ。実装も。 実装を強制する方法はないが、その必要もない。 自前で実装済みかどうかを判定して対応するのみ。 (定義を確認する方法がないのなら困ったことになるが、 それでも最悪try-catchは出来ると思うが、駄目なのか?)
- 445 名前:デフォルトの名無しさん mailto:sage [2016/08/28(日) 21:46:13.45 ID:+mkoP4gZ.net]
- >>425
> 構造体 これはShapeがクラスではなく構造体だった仮定か? それは最初から間違いで、クラスにしてもらうしかない。 どのやり方がいいのかは合意をとる必要はないけど、 俺が思うには「拡張メソッドで多態」が出来れば全て満足で上手く行く。 現状の拡張メソッドの仕様では旨味が無く、使いどころがない。 正直C#でこの手の「残念仕様」を見るのは初めてで、少し驚きだ。 (C#の仕様はどれもこれも何を意図しているか大体分かるものばかりだった) ただ、やる気だけの問題だと思うから、今後拡張される可能性はあると俺は思うけど。
- 446 名前:デフォルトの名無しさん mailto:sage [2016/08/28(日) 21:52:14.06 ID:veN4TyYm.net]
- >>427
そんな自分で自分の足を打ち抜くような機能が入るわけないじゃんw
- 447 名前:デフォルトの名無しさん mailto:sage [2016/08/28(日) 21:55:53.66 ID:+mkoP4gZ.net]
- 追加
>>424 その場合、仮にdll側で拡張メソッドを実装してくれていたとしても、インポート出来ないだろ。 こちら側がコンパイル時に見えてないと駄目なんだからさ。 だから今の仕様は「全部自前で用意しろ」なんだよ。 俺もそれでいいと思うし。 拡張メソッドを実装したクラスをインポートするっていうことも出来る(ようになる)のかもしれんが。
- 448 名前:デフォルトの名無しさん mailto:sage [2016/08/28(日) 22:01:29.02 ID:xWdxGs/J.net]
- これを15年前の世界から書き込んでるのだから、彼は凄いよ。
virtualも拡張メソッドも理解出来てなくて仕方ない。まともな動作環境すらない世界で仕様を理解しようと、間違ったことをワザと書いて、我々に答えさせてるんだから。
- 449 名前:デフォルトの名無しさん mailto:sage [2016/08/28(日) 22:20:25.25 ID:23NihOTg.net]
- C#の拡張メソッドをJavaScriptのプロトタイプ拡張と同じ感覚で考えてんのかね
スクリプト言語やりすぎると頭おかしくなるってのは本当だったんだ
- 450 名前:デフォルトの名無しさん mailto:sage [2016/08/28(日) 22:24:20.01 ID:ev9L5f83.net]
- javascriptでもプロトタイプ拡張は99.9%バッドプラクティスだけどな
気づくのに数年掛かった(prototype.jsが持て囃された期間を考えてみたまえ)程度にあいつらフロントエンジニア共は馬鹿だ
- 451 名前:デフォルトの名無しさん mailto:sage [2016/08/28(日) 22:46:16.98 ID:hQF+q+Zk.net]
- >>426
それがC#の設計思考とずれてるんだよ。 できるならば静的に解決したい。コンパイルに通ったならメソッドが存在し、存在することを前提に最適化したい。 ただの静的メソッド呼び出しだったのに、動的に確認する分かなりコストが高くなる。数万の木構造にやるなら1msが命取り あとは、それを実装すると名前解決が異常に複雑になり、今後の言語拡張の障害にもなるな その程度で良いならRoslynを使ってVSのプラグインでshape.Draw()ってコードをパターンマッチングに展開するプラグインを作ればいいんじゃないかな。
- 452 名前:デフォルトの名無しさん mailto:sage [2016/08/28(日) 23:08:26.53 ID:+mkoP4gZ.net]
- >>433
何について言っている? 「拡張メソッドの多態」についてなら、既に言ったようにローカルに多重継承させればいいだけ。 実装自体も無理はないし、動作速度も問題ないと思うよ。 各クラスのvtableをコピーすることにはなるけど、 オブジェクトを直接vtableに載せていることはないだろうし、 コピー領域は、sizeof(void*)*フィールド個数 Bytes でしかない。 もちろん他の実装も出来るだろうし、いずれにしても必要になればMSが検討すればいいだけ。 多分ここら辺の話が通じないのは、君がvtableの実装を理解出来ていないのだと思うよ。 それは>>414にあるURLを全部読めばいい。 C++やC#のコンパイル言語は、メソッドは動的に名前で解決するわけではないんだよ。 (なおJavaScriptは全面的に動的解決だが、それでもC#の1.5倍ほど遅いだけ。) 俺は「拡張メソッドの多態」は欲しいと思う。 君はこれについて「要らない」のか「欲しいけど出来ないという意見」なのかはっきりしないが。
- 453 名前:デフォルトの名無しさん mailto:sage [2016/08/28(日) 23:14:10.11 ID:rlU+i3Q+.net]
- そんな極々ニッチな需要のためにMSが動くわけないだろ
そんなに自分のアイデアが優れてると思うなら実装して然るべき場所で評価してもらえよ 今やコンパイラもオープンな時代だから出来ないことはない 良い加減うっとおしいんだよ 攻撃的な口調で長文連投すんなハゲ
- 454 名前:デフォルトの名無しさん mailto:sage [2016/08/29(月) 00:39:03.09 ID:0+IBopma.net]
- >>434
こちらのvtableの知識を疑う前に、staticがvtableにあると勘違いしていた理由を考えるとかC#の勉強するとかしたほうが良いかと プラグイン等により拡張メソッドを持たないインスタンスが渡ることを考慮し、vtableの実行の前に存在判定が必要で結構コストになる また、Javascriptが早いのはJITが鬼のように最適化してるからで、そこまで考えるとstaticメソッドのインライン展開が妨害されるとか、 質問としては、vtableのコピーでなんでフィールドの個数が出てくるの? あと、別のファイルだと別の拡張メソッド呼び出しになるかもしれんが、どのタイミングでインスタンスのvftable書き換えるの? その場合、拡張メソッドの呼び出しはすべてスレッドセーフじゃなくなる? 今のところメリットが0とは言わないが、メリット<<<実装の手間、影響
- 455 名前:デフォルトの名無しさん mailto:sage [2016/08/29(月) 00:58:40.06 ID:bQrj623w.net]
- C#でアスペクト注入したい
RealProxyか実行時コンパイル以外に手段はある?
- 456 名前:デフォルトの名無しさん mailto:sage [2016/08/29(月) 14:42:36.92 ID:iNmqLiUV.net]
- c#を主に使っていて時々php書くとphpが使いにくいてイライラするのですが、皆さんそういう事有りますか?
- 457 名前:デフォルトの名無しさん mailto:sage [2016/08/29(月) 14:53:02.96 ID:fXL0TTLw.net]
- >>438
フツー
|

|