C#(。NET)の設計上の欠陥[クローズ]


84

C#または.NET Framework全般の最大の設計上の欠陥は何ですか?

例:NULL不可の文字列型はなく、IDataReaderから値をフェッチするときにDBNullをチェックする必要があります。


それらの設計上の欠陥はどのような意味ですか?
ジュリエット

IDataReaderを使用すると、手動でチェックするのではなく、IsDBNullを使用できます
MarcGravell

9
封印されたクラスについて話すためのキュージョンスキート;)
johnc 2009年

3
拡張メソッドを使用してIDataReaderを修正するのは非常に簡単です。weblogs.asp.net/ skillet / archive / 2008/06/18 /…を参照してください。
ロバートロスニー2009年

@ lagerdalek-できればそのコメントを+1します。よく覚えている
MarcGravell

回答:


39

私はこの投稿に強く同意します(ToStringがないことをうんちする人のために、クラスにカスタム形式を提供するデバッガー属性があります)。

上記のリストに加えて、次の合理的なリクエストも追加します。

  1. null許容値型を補完するものとしてのnull許容でない参照型。
  2. 構造体の空のコンストラクターのオーバーライドを許可し、
  3. ジェネリック型制約が封印されたクラスを指定できるようにし、
  4. 私は、制約として使用されるときに任意のコンストラクター署名を要求した別のポスターに同意します。どこT : new(string)、またはどこT : new(string, int)
  5. また、空のイベントリストと同時設定の両方でのイベントの修正に関する別のポスターにも同意します(後者は注意が必要ですが)。
  6. 演算子は、クラスの静的メソッドとしてではなく(または、少なくとも静的メソッドとしてだけではなく)、拡張メソッドとして定義する必要があります。
  7. インターフェイスの静的プロパティとメソッドを許可します(Javaにはこれがありますが、C#にはありません)。
  8. オブジェクト初期化子でイベントの初期化を許可します(現在、フィールドとプロパティのみが許可されています)。
  9. 「オブジェクト初期化子」構文がオブジェクトの作成時にのみ使用できるのはなぜですか?いつでも利用できるようにしてみませんか。var e = new Foo(); e { Bar = baz };
  10. 二次列挙可能な動作を修正し
  11. すべてのコレクションには、反復のための不変のスナップショットが必要です(つまり、コレクションを変更してもイテレーターが無効になることはありません)。
  12. タプルは簡単に追加できますが、「Either<T>」のような効率的な閉じた代数型はそうではないので、閉じた代数型を宣言し、それに徹底的なパターンマッチングを適用する方法が欲しいです(基本的にはビジターパターンのファーストクラスのサポートですが、はるかに効率的); したがって、列挙型を取得し、徹底的なパターンマッチングのサポートでそれらを拡張し、無効なケースを許可しないでください。
  13. 一般的なパターンマッチングのサポートが欲しいのですが、少なくともオブジェクトタイプのテストはサポートしたいと思います。また、ここの別の投稿で提案されているswitch構文も好きです。
  14. System.IOようなクラスのStream設計がやや不十分であるという別の投稿に同意します。スローするためにいくつかの実装を必要とするインターフェイスNotSupportedExceptionは、悪い設計です。
  15. IListそれよりもはるかに単純なはずです。実際、これは、などの具体的なコレクションインターフェイスの多くに当てはまる可能性がありますICollection
  16. IDictionaryなど、メソッドが多すぎると例外がスローされます。
  17. 私は、Javaで利用可能なものよりも優れたチェック済み例外の形式を好みます(これを行う方法については、タイプおよびエフェクトシステムに関する調査を参照してください)。
  18. ジェネリックメソッドのオーバーロード解決におけるさまざまな厄介なコーナーケースを修正します。たとえば、2つのオーバーロードされた拡張メソッドを提供してみてください。1つは参照型で動作し、もう1つはnull許容の構造体型で動作し、型推論がどのようにそれを好むかを確認します。
  19. INotifyPropertyChangedフィールド名を文字列として受け取る、のようなインターフェイスのフィールド名とメンバー名を安全に反映する方法を提供します。これを行うには、ラムダをaMemberExpressionで取る拡張メソッドを使用します。() => Foo、しかしそれはあまり効率的ではありません、
    • 更新:C#6.0nameof()は単一メンバー名の演算子を追加しましたが、ジェネリックでは機能しません(nameof(T) == "T"実際の型引数の名前の代わりに:実行する必要がありますtypeof(T).Name))-また、「パス」文字列を取得することもできませんたとえばnameof(this.ComplexProperty.Value) == "Value"、可能なアプリケーションを制限します。
  20. インターフェイスで演算子を許可し、すべてのコア番号タイプに実装させIArithmeticます。他の便利な共有オペレータインターフェイスも可能ですが、
  21. オブジェクトのフィールド/プロパティを変更するのを難しくするか、少なくとも、不変のフィールドに注釈を付けて、型チェッカーに強制させます(これは、クリスケスのゲッターのみのプロパティとして扱います。難しくはありません)。実際、両方を持つことに意味がないため、フィールドとプロパティをより賢明な方法で統合します。C#3.0の自動プロパティは、この方向への第一歩ですが、十分に進んでいません。
    • 更新:C#にはreadonlyキーワードがあり、C#6.0では読み取り専用の自動プロパティが追加されましたが、不変の型と値に対する真の言語サポートほど厳格ではありません。
  22. コンストラクターの宣言を簡素化します。私はF#のアプローチが好きですが、クラス名の代わりに単に「新しい」を必要とするここの他の投稿は、少なくとも、より良いです、

今のところそれで十分だと思います。これらはすべて、私が先週遭遇した苛立ちです。本当に気をつければ、おそらく何時間も続けることができるでしょう。C#4.0はすでに名前付き、オプション、デフォルトの引数を追加していますが、これは私が強く承認します。

今、1つの不合理な要求のために:

  1. C#/ CLRが型コンストラクターのポリモーフィズムをサポートできれば、本当に素晴らしいでしょう。ジェネリックよりもジェネリック、

かなりお願いしますか?:-)


1
#1に関しては、すべての型にデフォルト値が必要であるか、特定の型の変数またはフィールドが割り当てられるたびにシステムがコンストラクターを実行する手段を提供する必要があります。私は後者(#2の派生物)を好みますが、非仮想メソッド/プロパティを装飾してnullチェックなしで呼び出すように指定できれば、#1に対応できます。これにより、「String」フィールドなどが、デフォルトでnullではなく空の文字列であるかのように動作できるようになります(Stringの静的な「length」関数はnull文字列で呼び出された場合に0を返す可能性があるため)。
スーパーキャット2011年

1
#2に関しては、一般に、構造体がfill-with-zero以外のコンストラクターだけでなく、byte-for-byte-copy以外のコピーコンストラクターも指定できると便利です。実際、私は、エンティティが値または参照セマンティクスを持っている可能性があることを認識し、値型ヒープオブジェクトに可変、共有不変、またはコミットされていないタグを付けることができる、.netのようなフレームワークを本当に望んでいます。 (コミットされていない値オブジェクトは、モードが最初にCompareExchangeで変更可能になった場合に変更されるか、モードが最初にCompareExchangeで共有された場合に共有される可能性があります)。
スーパーキャット2011年

1
優れた点!#1の場合、型システムアノテーションが一般的な解決策ですが、T:new()などの型変数を介してコンストラクター制約を伝播することを好みます。Re:#2、コピーコンストラクターについての良い点ですが、上記の行に沿ったより一般的なコンストラクターに満足しています。さらに良いのは、コンストラクターを識別メソッドとして完全に排除し、単純に静的メソッドにすることです。これにより、特にインターフェイスで静的メソッドを許可する場合に、より単純で一般的な構築パターンが可能になります。Constructors-as-static-methods + static-methods-in-interfacesも#1を解決します。
2011

3
#3:ジェネリック型パラメーターとして封印されたクラスを使用する意味は何ですか?たとえば、Foo <T>ここでT:string?#11:わかりました、それで私はList<T>百万のTを持っています。スナップショットを効率的に作成することをどのように提案しますか?#21:使用するreadonlyキーワードを....ここにいくつかの良い提案がありますが、それらはほとんどそれだけです-提案であり、設計上の欠陥ではありません。
qwertie 2012

2
これは非常に興味深い答えですが、C#6の機能で更新する必要があると思います。例:アイテム19と21が実装されました=)
eduardobr

72
  • 上のReset()方法IEnumerator<T>は間違いでした(イテレータブロックの場合、言語仕様はこれが例外をスローすることさえ要求します)
  • 配列を返すリフレクションメソッドは、エリックの見解では間違いでした
  • 配列の共分散は奇妙であり、今もなお奇妙です
    • 更新:.NET 4.0を使用するC#4.0では、ジェネリックインターフェイス(IEnumerable<out T>およびFunc<in T, out TResult>などList<T>)に共変/反変性のサポートが追加されましたが、具体的な型(など)は追加されていません。
  • ApplicationException むしろ不利になりました-それは間違いでしたか?
  • 同期されたコレクション-良いアイデアですが、実際には必ずしも役立つとは限りません。通常は同期する必要があります Contains複数の操作する(、then Add)、個別の操作を同期するコレクションはそれほど有用ではありません。
    • アップデート:タイプSystem.Collections.Concurrent、とはTryAddGetOrAddTryRemove、などは、.NET Framework 4.0で追加されました-工場出荷時のデリゲートを受け入れる方法は、工場でのみ、キーごとに一度呼び出されます保証するものではありませんが。
  • より多くの使用が行われた可能性があります using/lockパターンをかもしれません-おそらく、再利用可能な(拡張可能な?)構文を共有できるようになります。を返しIDisposable、使用することでこれをシミュレートusingできますが、より明確であった可能性があります
  • イテレータブロック:(怠惰ではなく)事前に引数をチェックする簡単な方法はありません。確かに、2つの連鎖メソッドを書くことができますが、それは醜いです
  • より単純な不変性があればいいでしょう。C#4.0は少し、十分ではありません
  • 「このref-typeパラメーターをnullにすることはできません」のサポートはありません-コントラクト(4.0)はこれをいくらか助けますが。しかし、次のような構文Foo(SqlConnection! connection)(nullチェック/を挿入する)のthrowは良いでしょう(int?などとは対照的です)
  • ジェネリックスを使用した演算子およびデフォルト以外のコンストラクターのサポートの欠如。C#4.0はこれを少し解決しますdynamicます。または、次のように有効にすることもできます
  • 宣言されているイテレータ変数 は、foreach展開中にwhileの。つまり、anon-methods / lambdasは、反復ごとに1つではなく、単一の変数をキャプチャします(スレッド化/非同期などで苦痛)

IEnumerable!= IEnumerable <object>は確かに奇妙です
Rauhotz 2009年

2
IEnumerableは1.1の二日酔いです。少なくともLINQで.Cast <object>()を使用できます
MarcGravell

8
BCLの人々は、それApplicationExceptionは間違いだと言いました-彼らが望んでいたほど役に立たなかったのです。彼らはまたそれがあったSystem.Exceptionはずだと言ったabstract
ジェイバズジ2009年

2
null許容不可:通常の参照型Tをnull許容不可能なTを取るものに渡すと、コンパイルエラーになります。(int?をintに渡せないのと同じように)。もちろん、反対方向を通過することは問題ありません。
ジェイバズジ2009年

1
@Jon Harrop:IMHO、不変の配列と読み取り専用の配列参照がサポートされているはずです。おそらく、他のいくつかの配列バリアント(たとえば、「サイズ変更可能な配列」(間接参照)、またはオフセットと境界を持つ配列参照)の場合もあります。
スーパーキャット2010年

60

TextWriterはベースです StreamWriterのクラスです。wtf?

それはいつも私を極端に混乱させます。


19
+1毎回調べなければなりません。(Whaddayaは、 TextWriter()を新しくできないこと意味しますか?)
Nicholas Piasecki

1
神に感謝します...私はそれが私だけだと思いました。
IJケネディ

?これは常にテキストを書き込むものですが、StreamWriterのみがストリームに書き込みます。かなり簡単なようです。
ジョンハンナ

4
StreamWriterという名前は、テキストをIMOで十分に明白に書き込むという事実を示していません。それは単にバイトを書き込むように孤立して聞こえ、TextWriterは(string toWrite)のAPIをバイトに変換する上に凝った実装になるでしょう。今、それがStreamTextWriterと呼ばれた場合、確かに、それはすぐに明らかですが、少し長いです:(
奇妙な2012年

44

小さなC#petpeev-コンストラクターはC ++ / Java構文を使用して、コンストラクターをクラスと同じ名前にします。

New()またはctor()はるかに良かったでしょう。

そして確かに、coderushなどのツールを使用すると、クラスの名前を変更する際の問題は少なくなりますが、読みやすさのPOVから、New()は非常に明確になります。


えーと、新しいインスタンスを作成しようとしているものをどうやって知るのでしょうか?
BlueRaja-Danny Pflughoeft 2010

4
@BlueRaja:スコットはクラスのコンストラクターの命名について言及しています。class Foo { new(int j) {i = j} int i; }
dalle 2010

私は100%同意しますが、ctor()またはconstructor()の方が優れていたでしょう( New --uppercaseキーワードは慣例に反し)、設計上の欠陥と呼ぶことを躊躇します。彼らは既存のC ++ / Java開発者を引き付けたいと考えていました。そして、多くの愚かな古い構文規則を借りることで、間違いなく彼らの目標を達成することができました。
qwertie 2012

この質問に関連するもの:stackoverflow.com/questions/32101993/c-sharp-sorted-linkedlistMergeSort、bucketsort、またはその他の並べ替えアルゴリズムを使用してLinkedListを単純に並べ替える方法はありません(.NETのみを使用)が、はるかに遅いlinqを使用しますアドホック実装よりも。
CoffeDeveloper 2015

29

私はあなたができないことを理解していません

ここで、T:new(U)

したがって、ジェネリック型Tにはデフォルト以外のコンストラクターがあることを宣言します。

編集:

私はこれをしたい:

public class A 
{
    public A(string text) 
    {

    }
}


public class Gen<T> where T : new(string text) 
{

}

ジェネリック型は、その型のオブジェクト、つまりそれらのインターフェースをどのように使用するかを宣言します。コンストラクターは、そのインターフェースの実装の詳細であり、コンシューマーの関心事ではありません。パラメータ化されたインスタンスを作成する必要がある場合は、ファクトリを使用してください。
ブライアンワッツ

参考までに、コンパイル時のチェックはできませんが、MiscUtilには、デフォルト以外のコンストラクター(ジェネリック)を効率的に使用するためのコードがいくつかあります。つまり、Activator.CreateInstanceまたはリフレクションがありません。
MarcGravell

それは意味がなく、いくつかの用途で混乱するからです。それでも、不変のオブジェクトを操作する場合に役立ちます。
ポップカタリン

7
一般的に、メンバーの制約がないことは厄介です。
MichaelGG 2009

3
アーメン、私はいつもこれが欲しかった
スティーブ

20

私がこれに最初に言及したことに本当に驚いています:

ADO.NET型付きデータセットは、null許容型のプロパティとしてnull許容列を公開しません。あなたはこれを書くことができるはずです:

int? i = myRec.Field;
myRec.Field = null;

代わりに、これを書く必要がありますが、これはばかげています。

int? i = (int?)myRec.IsFieldNull() ? (int?)null : myRec.Field;
myRec.SetFieldNull();

これは.NET2.0では厄介でしたが、きちんとしたLINQクエリで上記のようなジゲリーポケリーを使用する必要があるため、さらに厄介です。

生成されたAdd<TableName>Rowメソッドがnull許容型の概念に同様に無意味であることも厄介です。生成されたTableAdapterメソッドはそうではないので、なおさらです。

.NETには、開発チームが「わかりました。もうすぐです。出荷してください」と言ったような気がするものはあまりありません。しかし、これは確かにそうです。


私は心から同意します!これは私がそれを使わなければならないたびに私を悩ませます(それはしばしばです)。ああ!+1
Eyvind

2
少なくとも彼らができることは、全体を通してDBNullの代わりにnull許容値型を使用する新しいDataSetV2クラス(悪い名前-引数のためだけに)を思いつくことです。
クリスチャンヘイター

それ自体がNULLを表すのに完全に適切DBNull.Valueであった場合に、特別な値を要求するという不条理を忘れないでくださいnull。幸い、LINQ-to-SQLはNULLにnullを使用します。
qwertie 2012

実際、その不条理は、不条理な建物全体が構築された岩です。
ロバートロスニー2012

20
  1. 私はStream、StringWriter、StringReader、TextReader、TextWriterクラスの大ファンではありません...何が何であるかは直感的ではありません。
  2. IEnumerable.Resetは、イテレータの例外をスローします。データバインド時に常にリセットを呼び出すサードパーティコンポーネントがいくつかあり、これらを使用するには最初にリストにキャストする必要があります。
  3. Xmlシリアライザーにはシリアル化されたIDictionary要素が必要です
  4. HttpWebRequest&FTP APIのことをすっかり忘れてしまいました...(ニコラスがこれを思い出させてくれたコメントに感謝します:-)

編集
5.私のもう1つの厄介な点は、System.Reflection.BindingFlagsが、使用するメソッドに応じてどのように異なる用途を持っているかです。たとえばFindFieldsでは、CreateInstanceまたはSetFieldはどういう意味ですか?これは、混乱を招くこの列挙の背後にある意味を過負荷にした場合です。


1
+1 XmlTextWriter、TextWriterなどのクラスを毎回検索する必要があります。HttpWebRequest / Responseのものと同じです。そこには完全に直感的でないAPIがあります。
ニコラスピアセッキ

+ 1-1 = 0:XmlTextWriterなど、名前からそれらが何であるかを真に推測することは不可能であることに同意します。HttpWebRequest私はそれが非常に直感的だと思うことに同意しません。
AnthonyWJones 2009年

それぞれに私は思う。FTPでは、彼らが持っているものよりも高いレベルの抽象化を期待していると思います。
JoshBerke 2009年

15

設計上の欠陥だと言っても過言ではありませんが、VBと同じ方法でラムダ式を推測できれば本当に素晴らしいと思います。

VB:

Dim a = Function(x) x * (x - 1)

C#

これができればいいのですが:

var a = x => x * (x - 1);

これを行う代わりに:

Func<int, int> a = x => x * (x - 1);

それほど長くはないことはわかっていますが、コードゴルフではすべてのキャラクターが気の毒です!彼らはこれらのプログラミング言語を設計するときにそれを考慮に入れていませんか?:)


3
マイクロソフトは、言語を設計するときにコードゴルフを考慮に入れる必要がありますか?
jrcs3 2009年

3
@Ray Burns:VBでどのように認識しますか?VBはそれをサポートしていますが、違いは何ですか?
BenAlabaster 2009年

3
@RayBurns型推論?私は1989
。– RD1

3
LamdasはC#では同像性です。フラグメント(int x) => x * (x -1);は意味するFunc<int, int>ことも、意味することもありますExpression<Func<int, int>>
Scott Weinstein

3
@BenAlabaster:VBはレイトバウンド算術演算子をサポートしています。C#はコンパイル時にそれらを解決する必要があります。それは言語の違いです。たとえば、VBは2つのオブジェクトを一緒に追加できます。に+定義されていないため、C#はできませんobject
再帰的

14
  1. System.Objectのクラス:

    • EqualsとGetHashCode-すべてのクラスが比較可能またはハッシュ可能であるとは限らないため、インターフェイスに移動する必要があります。IEquatableまたはIComparable(または同様のもの)が思い浮かびます。

    • ToString-すべてのクラスを文字列に変換できるわけではないため、インターフェイスに移動する必要があります。IFormattable(または同様のもの)が思い浮かびます。

  2. ICollection.SyncRootのプロパティ:

    • 貧弱なデザインを促進し、外部ロックはほとんどの場合より便利です。
  3. ジェネリックは最初からそこにあるべきでした:

    • System.Collectionsの名前空間は、多かれ少なかれ、廃止されたクラスとインタフェースの多くが含まれています。

1
1.これらのメソッドは非常に一般的であるため、奇妙なケースは問題ないと判断されました。誰かがクラスでObject.Equalsを呼び出すことができるかどうかは重要ですか?実装がある場合とない場合があることが知られており、99%のクラスでIEquatable、IFormattableを要求するのは奇妙です。
Guvante 2009

1
たとえば、デフォルトの参照等価性を使用して、ユーザー定義オブジェクトをキーとして使用して辞書を作成できると便利です。その目的でユーザー定義オブジェクトにコードを明示的に追加する必要はありません。Finalizeははるかに大きな無駄だと思います(より良い代替策は、finalizationを実装する必要があるオブジェクトにiFinalizableを実装し、finalizeのために明示的に登録することでした)。OTOH、コンストラクターが例外をスローした場合にDisposeを呼び出すなど、iDisposableにはより固有のサポートが必要でした。
スーパーキャット2010年

1
@supercat:必要なのはEqualityComparer<T>.Default正しく更新することだけです。次に、var dict = new Dictionary<object, string>(EqualityComparer<object>.Default)との両方var dict = new Dictionary<object, string>()が参照比較/同等性を使用します。
dalle 2010年

1
@supercat:あなたが説明することはまさに何をするかEqualityComparer<T>.Defaultです。ルックアップのたびにチェックする必要はありません。比較子はDictionaryインスタンスのプロパティであり、それぞれDictionaryが使用しているものを認識しています。
dalle 2010年

1
@supercat:ディクショナリは、最も一般的な型(つまり、共通の基本クラス)をキーとして使用する必要があります。同じディクショナリで文字列とDateTimeの両方を使用しても、参照比較を使用しない限り、ユーザー定義の比較が提供されない限り、意味がありません。です。このトピックの名前は「C#(。NET)設計の欠陥」であることを忘れないでください。
dalle 2010年

12

私を苛立たせるものの1つはPredicate<T> != Func<T, bool>パラドックスです。これらは両方ともタイプのデリゲートT -> boolですが、割り当てとの互換性はありません。


Delegate.Createといくつかのキャストを使用して変換を行うトリックがありますが、少なくとも明示的なキャストを実行できると便利です(ただし、暗黙的なサポートがないことは理解できます)
Guvante 2009

一般に、デリゲートの設計には欠陥があります。たとえば、弱いイベントの欠如(サブスクライバーからの特別な努力なしにソース側の弱いイベントを実装するには、一連のリフレクションとReflectionPermissionを使用する必要があります。codeproject.com/ Articles / 29922 / Weak-Events-in-Cを参照してください)、デリゲートは参照型でなければならないという要件に起因する非効率性(デリゲートは値型であった場合、より高速で、多くの場合、1/3のメモリを使用していました。その場合、それらは単にペアになります。スタックに渡すことができるポインター。)
Qwertie 2012

11

一部の人々(ISV)は、dotNetランタイムを必要としないネイティブ実行可能ファイルを作成するために、ビルド時にマシンコードにコンパイルしてリンクできることを望んでいます。


実行する前に、プログラムをNGENできるはずです。
オタビオデシオ2009年

ランタイムの依存関係を削除することと同じではありません。コードに対して実行された最初のJITのみを保存します。
Ed S.


これを行う難読化ツールはありませんか?フレームワークがexeに埋め込まれるため、デプロイする必要はありません。名前を覚えることができません...プリエンプティブではありません...– JoshBerke
1

2
XenocodeのPostbuildはそれをしませんか?Visual Studioにこれを行う方法があれば、それは素晴らしいことです...
BenAlabaster 2009年

11

私たちは権利について多くを知っていますOOテクニックます。デカップリング、コントラクトによるプログラミング、不適切な継承の回避、例外の適切な使用、オープン/クローズドプリンシパル、リスコフの置換可能性など。まだ、.Netフレームワークはベストプラクティスを採用していません。

私にとって、.Netの設計における最大の欠陥は、巨人の肩の上に立っているわけではありません。フレームワークを使用するプログラマーの大衆に、理想的とは言えないプログラミングパラダイムを宣伝する

MSがこれに注意を払っていれば、ソフトウェアエンジニアリングの世界は、この10年間で品質、安定性、スケーラビリティの面で大きな飛躍を遂げた可能性がありますが、残念ながら、後退しているようです。


4
目標通りの暴言の場合は+1。これに加えて、すべてのクラスをサブクラス化できないこと、基本クラスのインターフェイスがないこと、数年経ってもフレームワークのバグを修正することに抵抗があることを追加します
Steven A. Lowe

1
追い詰めると、.Net Frameworkが非常に悪いため、どの欠陥が最悪であるかを判断するのが難しいと言っているのでしょうか。MSファンの少年たちに怒鳴られることを期待していたので、ベントの後は気分が良くなり、賛成票に感謝します。
ダニエルポール

私はどちらの方法にも投票していません。とにかく、私は反対票を投じることに非常に消極的ですが、なぜ私が気にしないのかを理解しようとしています。
Mike Dunlavey 2009年

2
あなたは「それができるほど良くない」と言っていると思いますが、それは答えではありません。何も完璧ではありません。詳細を提供します。
jcollum 2009年

3
いいえ、デザインに明らかに欠陥がある場合がたくさんあると言っていますが、それが正しいと思っても、それでも間違っています。たとえば、MSDNフォーラムへの私の投稿は次のとおり
Daniel

11

C#のswitchステートメントが好きではありません。

こんなもの欲しい

switch (a) {
  1    : do_something;
  2    : do_something_else;
  3,4  : do_something_different;
  else : do_something_weird; 
}

したがって、これ以上の中断(忘れやすい)や、異なる値をコンマで区切る可能性はありません。


実際、C#の他のすべてのように、単一のステートメントまたは中括弧で囲まれたブロックのいずれかが必要な場合は、さらに良いと思います。フォールスルーする機能がないと、現在のブレーク構文は少し危険であり、スコープにも制限されません。(AFAIK、それは、私にはわかりません)
Tamas Czinege 2009年

どういう意味かわかりません。独自の「理想的な」switchステートメントをここに投稿してください。フォールスルーしたくありませんが、コンマで区切られた値です。
tuinstoel 2009年

8
ちなみに、私はOPに同意します。switchCの意図的に不自由なバージョンをエミュレートするすべての言語で根本的に壊れています(速度が最適化されています!)。VBの方がはるかに優れていますが、パターンマッチングを使用する言語(Haskell、F#…)よりもまだ光年遅れています。
Konrad Rudolph

1
tuinostel:switch(a){case 1 {do_something; }ケース2 {do_something_else; }}-つまり、breakステートメント
削除し

2
ブレークがあることは一般的に間違いのように思えますが、それを発行するのはコンパイルエラーではありませんか?CからC#への移行を容易にするためだけにあるようです(別名、自動フォールスルーできないことを開発者に教える)
開発者に教える

10

リスナーを明示的にチェックする必要があるC#のイベント。たまたまそこにいた人に放送するというのがイベントのポイントではなかったのでしょうか。ないのに?


1
あなたがそれを望むときにこれのための砂糖がないのは迷惑です、なぜ彼らがそれを難し​​いのかわかります、それは必要がなければイベントの議論をインスタンス化しないことを奨励します
ShuggyCoUk 2009

うーん。私は理解していないか、同意しないか、またはその両方です:-)。何かをインスタンス化することに落胆したとは言えません。これは私には時期尚早の最適化のようなにおいがします。
Thomas Eyde 2009

場合によっては、部分的な方法が実行可能な代替手段です。
ロバートハーベイ

PLUSすべてこの原因を連結する... MSはCABの修正の両方これらの問題を持っていますが、CABは、(イベント・トピックとして、例えば、文字列ではなく、列挙型。)多くのC#での限界への独自の原因の問題を抱えている-なぜちょうど緩くしません-言語の一部である結合イベント!?
BlueRaja-Danny Pflughoeft 2010

9

ネストされた/再帰的なイテレータのひどい(そしてほとんどの人にはまったく見えない)O(N ^ 2)の振る舞い

私は彼らがそれについて知っていることを非常にうんざりしています それを修正する方法をますが、それは包含に値する十分な優先順位を持っているとは見なされていません。

私は常にツリーのような構造で作業しており、このように非常に高価な操作を誤って導入した場合は、そうでなければ賢い人々のコードを修正する必要があります。

「yieldforeach」の利点は、構文が単純で簡単なため、正確でパフォーマンスの高いコードが促進されることです。これは、プラットフォームの長期的な成功のために新しい機能を追加する前に、彼らが目指すべき「成功の落とし穴」です。


これは特に欠陥があります。これは、Oの動作の直感的な期待に反し、多くの人々を罠にかけるためです
oefe 2009

7

一部のクラスはインターフェイスを実装しますが、そのインターフェイスのメソッドの多くは実装しません。たとえば、ArrayはIListを実装しますが、9つのメソッドのうち4つはNotSupportedExceptionhttp //msdn.microsoft.com/en-us/library/system.array_membersをスローします。 .aspx


配列内の要素の数を変更することはできないので、Add、Clear、Insert、およびRemove(At)でできることは、NotSupportedをスローする以外にありません...実際、IListの実装でtrueを返すものはすべて期待されます。 IsFixedSizeはそれらをスローします。
CB

@CBはパーティーに少し遅れていると思います:)しかし、Arrayが "IList"を満たすことができない場合、なぜそれを実装するのですか?これは、SOLIDの原則におけるLの違反です。
ウィンガー

7

インターフェイスの静的メンバーとネストされたタイプ。

インターフェース部材は、インタフェースに固有のタイプのパラメータ(ある場合に特に有用であるなどenum)。列挙型をインターフェイス型にネストすると便利です。


1
これはあなたの他の提案と非常に似ていますか?
RCIX 2009年

1
いいえ、これはC#言語に関するもので、もう1つはフレームワークに関するものです。誰もが区別を気にするわけではないので、これは許可されるものについてであり、もう1つは提供されるものについてであると言わせてください。
ジェイバズジ2009年

6

イベントのひどく危険なデフォルトの性質。サブスクライバーが削除されたためにイベントを呼び出して一貫性のない状態になる可能性があるという事実は、ひどいものです。参照してくださいジョンスキートのエリックリペットの主題についての詳細読書のための優れた記事。


イベントがデフォルトでスレッドセーフでなくてもかまいません(シングルスレッドコードのパフォーマンスが向上する可能性があります)。ばかげているのは、追加/削除はデフォルトで安全ですが、イベントを発生させる自然な方法は安全ではなく、簡単に安全にする機能がないということです。
qwertie 2012

@Qwertie:ばかげているのは、かなり長い間、追加/削除はロックを使用しますが、それでもスレッドセーフではないということです。
スーパーキャット2012

6
  • null どこにでも。

  • const どこにも。

  • APIに一貫性がありません。たとえば、配列を変更voidするとリターンが返されますが、に追加するStringBufferと同じミュータブルが返されますStringBuffer

  • コレクションインターフェイスは、不変のデータ構造と互換性がありません。たとえばAdd、inSystem.Collections.Generic.IList<_>は結果を返すことができません。

  • 構造型はないのでSystem.Windows.Media.Effects.SamplingMode.Bilinear、単にBilinear

  • IEnumerator不変である必要があるときにクラスによって実装される可変インターフェースstruct

  • 平等との比較が混乱している:あなたは持っているSystem.IComparableし、Equalsしかし、あなたはまた、持っているSystem.IComparable<_>System.IEquatableSystem.Collections.IComparerSystem.Collections.IStructuralComparableSystem.Collections.IStructuralEquatableSystem.Collections.Generic.IComparerSystem.Collections.Generic.IEqualityComparer

  • タプルは構造体である必要がありますが、構造体は末尾呼び出しの除去を不必要に禁止するため、最も一般的で基本的なデータ型の1つが不必要に割り当てられ、スケーラブルな並列処理が破壊されます。


CLRには構造型がありませんが、構造型が型推論または「シンボル」と呼ばれるRuby機能と混同されているようです。構造型は、CLRがFunc <int、bool>とPredicate <int>を同じ型、または少なくとも暗黙的に変換可能であると見なした場合になります。
qwertie 2012

比較といえば、Comparer <T>を忘れないでください!
qwertie 2012

@Qwertie私はOCamlのポリモーフィックバリアントのようなプログラミング言語機能について言及していました。OCamlのLablGLライブラリには、グラフィックスのコンテキストで役立つ構造型付けの興味深い例がたくさんあります。型推論とは関係がなく、記号に接線方向にのみ関連しています。
JD

1
不変構造体をどのように使用しIEnumeratorますか?
スーパーキャット2012

5

列挙型として0月明かり

列挙型の特性: http //blogs.msdn.com/abhinaba/archive/2007/01/09/more-peculiarites-of-enum.aspx

この良い例で示されているように: http //plus.kaist.ac.kr/~shoh/postgresql/Npgsql/apidocs/Npgsql.NpgsqlParameterCollection.Add_overload_3.html

私の提案では、「@」記号を有効に活用してください。

の代わりに:

if((myVar&MyEnumName.ColorRed)!= 0)

これを使って:

if((myVar&MyEnumName.ColorRed)!= @ 0)


1
+1列挙型は、Javaが正しく実行した数少ないことの1つですが、C#は
正しく実行

5

すでに他の人が作った良い点の長いリストに追加するには:

  • DateTime.Now == DateTime.Now すべてではありませんが、ほとんどの場合。

  • String不変であるものには、構築と操作のための多くのオプションがありますが、StringBuilder(可変である)にはありません。

  • Monitor.Enterそして、Monitor.Exitインスタンスメソッドである必要があったので、ロックするために特定のオブジェクトを新しくする代わりに、を新しくしMonitorてロックすることができます。

  • デストラクタは、デストラクタと呼ばれるべきではありませんでした。ECMA仕様では、それらをファイナライザーと呼んでいます。これは、C ++の群集にとってはそれほど混乱しませんが、言語仕様では、それらをデストラクタと呼んでいます。


3
DateTime.Now一つは、世界で最も明白な競合状態ですが、残りの1
ダニーPflughoeft - BlueRaja

競合状態というほどではありませんが、彼らがそれを財産にしたという事実。プロパティはフィールドとまったく同じように見えるので、IMOの動作はかなり驚くべきものです。
ブライアンラスムッセン

4
@Brian Rasmussen:DateTime.Nowは、それを読み取ることによってではなく、外部要因によって変更されるため、非常に適切にプロパティです。SomeForm.Widthのようなプロパティを読み取り、ユーザーがフォームのサイズを変更した後、もう一度読み取ると、2回目の読み取りの値が異なります。最初のDateTime.Nowの実行に十分な時間がかかり、2番目のDateTime.Nowによって読み取られる値に影響を与える可能性がありますが、そのような効果は、実行に同じ時間がかかった他の関数と同じです。
スーパーキャット2011年

4

プロパティの使い方がイライラすることがあります。私はそれらをJavaのgetFoo()およびsetFoo()メソッドと同等のものと考えるのが好きです。しかし、そうではありません。

場合プロパティ使用上のガイドラインのプロパティは直列化ので、任意の順序で設定することができるはずという状態は、セッター時の検証のため、彼らがしている役に立たない、働くことができます。オブジェクトが無効な状態になるのを防ぎたい背景から来た場合、プロパティは解決策ではありません。時々私は私たちが物事の種類は、私たちがしているものに限られているので、彼らは、公共のメンバーよりも優れているだけでどのように見ることができないはずのプロパティで行うこと。

そのために、私は常に、プロパティ構文を何らかの方法で拡張できることを望んでいました(これは、ここではほとんど大声で考えています。このようなことができればと思います)。次のようなものを想像してみてください。


private string password;

public string Password
{
    // Called when being set by a deserializer or a persistence
    // framework
    deserialize
    {
       // I could put some backward-compat hacks in here. Like
       // weak passwords are grandfathered in without blowing up
       this.password = value;
    }
    get
    {
       if (Thread.CurrentPrincipal.IsInRole("Administrator"))
       {
           return this.password;
       }
       else
       {
           throw new PermissionException();
       }
    }
    set
    {
       if (MeetsPasswordRequirements(value))
       {
           throw new BlahException();
       }
       this.password = value;
    }
    serialize
    {
        return this.password;
    }
}

それが役立つかどうか、またはそれらにアクセスすることがどのように見えるかはわかりません。しかし、プロパティをさらに活用して、getメソッドやsetメソッドのように扱うことができればと思います。


3
シリアライザーにプロパティを呼び出させたくない場合は、そのようなことを行うためのISerializableインターフェイスと暗黙のコンストラクターが提供されていると思います。もう少し作業が必要ですが、その作業のほとんどはすでにメソッドで実行しているようです。
Guvante 2009

4

拡張メソッドは素晴らしいですが、ミックスインに関しては、実際のミックスインでよりクリーンに解決できた可能性のある問題を解決するための醜い方法です(ルビーを見て、私が話していることを確認してください)。それらを言語に追加するための本当に良い方法は、ジェネリックを継承に使用できるようにすることでした。これにより、既存のクラスをオブジェクト指向の優れた方法で拡張できます。

public class MyMixin<T> : T
{
    // etc...
}

これは、次のように使用して文字列を拡張できます。

var newMixin = new MyMixin<string>();

メソッドをオーバーライドできるため、拡張メソッドよりもはるかに強力です。たとえば、メソッドをラップして、言語内でAOPのような機能を使用できます。

暴言でごめんなさい:-)


5
興味深いですが、私は拡張メソッドを好みます。文字列の拡張メソッドの束を含むライブラリを取得した場合、新しいものを取得するために、MyMixin <string>へのすべての文字列参照を変更する必要はありません。確かにマイナーなことですが、メソッドの透過的な追加が拡張メソッドを非常に優れたものにしているのです。
RCIX 2009年

ところで、それがすでに機能していることをご存知ですか?
RCIX 2009年

2
LINQがこのように機能する方法がわかりません
BlueRaja – Danny Pflughoeft 2010

2
@RCIX:ミックスインは、拡張メソッドが機能するはずだと私が思っていたように聞こえます。拡張メソッドを暗黙的にすることの問題は、実際のクラスメンバーが拡張メソッドよりも優先される必要があることを意味します。拡張メソッドGraphics.DrawParallelogram(Pen p、Point v1、Point v2、Point v3)が定義され、後でDrawParallelogram関数が異なる順序でポイントを使用するSystem.Graphicsに追加された場合、拡張メソッドを使用するコードは警告。ところで、拡張メソッドに2つのドットを使用することに問題があったでしょうか(例:object..method()?)
supercat 2010年

3

Microsoftはフレームワークの明らかなバグを修正せず、エンドユーザーが修正できるようにフックを提供しません。

また、実行時に.NET実行可能ファイルにバイナリパッチを適用する方法も、ネイティブライブラリにバイナリパッチを適用せずに.NET Frameworkライブラリのプライベートバージョンを指定する方法もありません(ロード呼び出しをインターセプトするため)。ILDASMは再配布できないため、自動化できません。とにかくパッチ。


1
明らかなフレームワークのバグとはどういう意味ですか?
ロバートロスニー2009年

1
#1スクロール可能なコントロールの部分的に表示されている子コントロールをクリックします。コントロールは、MouseDownイベントを受信する前にビューにシフトされ、クリックがコントロール上の予想以外の場所に移動します。ドラッグ操作もトリガーするツリービューではさらに悪化します。
ジョシュア


3
  • null変数で拡張メソッドを呼び出すことができるかどうかは議論の余地があります。

    オブジェクトa = null; a.MyExtMethod(); //これは呼び出し可能であり、どこかでMyExtMethodが定義されていると想定します

    便利かもしれませんが、null参照の例外トピックについてはあいまいです。

  • 1つの命名「欠陥」。System.configuration.dllの「configuration」の「C」は大文字にする必要があります。

  • 例外処理。Javaのように例外を強制的にキャッチまたはスローする必要があり、コンパイラはコンパイル時に例外をチェックする必要があります。ユーザーは、ターゲット呼び出し内の例外情報のコメントに依存しないでください。


3
ただし、非常に便利です-パラメータチェック用の「ThrowIfNull」拡張メソッドがあります; -p
MarcGravell

2
あなたはこれを行うことができます?ugh ThrowIfNullこれは興味深い拡張機能ですが、これは間違っているようです。
JoshBerke 2009年

1
プレーンCLRでは、null参照でインスタンスメソッドを呼び出すことができます。メソッドがオブジェクトまたはそのフィールドにアクセスしない場合、呼び出しはnull参照例外をスローしません。(仮想メソッド以外でもcallvirtを使用するため、C#ではこれを行うことはできません)
Pop Catalin

7
例外は完全に間違っています。コールスタックでスローされる可能性のあるすべてのひどい例外をキャッチする必要がある場合は、すぐに失敗することはできません。しかし、特定の呼び出しとその結果の呼び出し

3
@Will:Javaと.netの両方で例外処理が厄介です。これは、使用されるメカニズムが、ある程度関連しているがある程度直交している3つの概念を密接に結び付けているためです。(1)どのタイプの問題が発生したか(配列境界エラー、 I / Oタイムアウトなど); (2)結果として特定のコードがアクションを実行する必要があるかどうか。(3)問題はどの時点で「解決済み」と見なされるべきか。IEnumerableから読み取られたデータでオブジェクトを変更することになっているルーチンについて考えてみます。そのIEnumerableの処理で例外が発生した場合はどうなりますか?
スーパーキャット2011年

3

フレームワークのV1のSqlCommandの.Parameters.Add()メソッドはひどく設計されていました-値(int)が0のパラメーターを渡した場合、オーバーロードの1つは基本的に機能しません-これにより、作成されましたSqlCommandクラスの.Parameters.AddWithValue()メソッド。


同意しますが、あなたはSqlCommand.Parameters.Add()メソッドを意味していると思います。
マットピーターソン

3
  1. とのサブセットはICollection<T>ありませんIList<T>。少なくとも、共分散の読み取り専用コレクションインターフェイスIListSource<out T>(列挙子、インデクサー、およびカウントを使用)は非常に便利でした。
  2. .NETは弱いデリゲートをサポートしていません。回避策はせいぜい不器用であり、リスナー側の回避策は部分的な信頼では不可能です(ReflectionPermissionが必要です)。
  3. 一般的なインターフェースの統合は、それが理にかなっていて問題がない場合でも禁止されています。
  4. C ++とは異なり、共変戻り型は.NETでは許可されていません
  5. 2つの値タイプが等しいかどうかをビット単位で比較することはできません。機能的な「永続的な」データ構造でTransform(Sequence<T>, Func<T,T>)、関数が同じ値を返すか異なる値を返すかをすばやく判断する必要がある関数を作成していました。関数が引数のほとんど/すべてを変更しない場合、出力シーケンスは入力シーケンスからの一部/すべてのメモリを共有できます。値型Tをビット単位で比較する機能がないと、はるかに遅い比較を使用する必要があり、パフォーマンスが大幅に低下します。
  6. .NETは、アドホックインターフェイス(GoやRustで提供されるインターフェイスなど)をパフォーマンスの高い方法でサポートできないようです。このようなインターフェイスを使用すると、クラスがそのインターフェイスを明示的に実装していなくてもList<T>、仮想IListSource<U>(T:Uの場合)にキャストできます。この機能を提供するために、少なくとも3つの 異なる ライブラリ(独立して記述)があります(もちろん、パフォーマンスの欠点があります。完全な回避策が可能である場合、それを.NETの欠陥と呼ぶのは公平ではありません)。
  7. その他のパフォーマンスの問題:IEnumeratorでは、反復ごとに2つのインターフェイス呼び出しが必要です。プレーンなメソッドポインタ(IntPtrサイズのオープンデリゲート)または値型デリゲート(IntPtr * 2)は使用できません。固定サイズの配列(任意の型T)をクラス内に埋め込むことはできません。ありませんWeakReference<T>(自分で簡単に書くことができますが、内部でキャストを使用します)。
  8. 同一のデリゲートタイプが互換性がないと見なされる(暗黙の変換がない)という事実は、場合によっては(Predicate<T>vsなどFunc<T,bool>)私にとって厄介なものでした。.NETでは、独立したDLLのクラスが同じインターフェイスを実装するだけでは不十分であるため、コンポーネント間の疎結合を実現するために、インターフェイスとデリゲートの構造型を設定できればと思うことがよくあります。インターフェイスを定義するDLL。
  9. DBNull.Valuenull同じ目的を同じようにうまく果たしたとしても存在します。
  10. C#には?? =演算子がありません。あなたは書く必要がありますvariable = variable ?? value。実際、C#には、不必要に対称性に欠ける場所がいくつかあります。たとえば、if (x) y(); else z();(中括弧なしで)書くことはできますが、書くことはできませんtry y(); finally z();
  11. スレッドを作成するときに、子スレッドに親スレッドからスレッドローカル値を継承させることはできません。BCLはこれをサポートしていないだけでなく、すべてのスレッドを手動で作成しない限り、自分で実装することはできません。スレッド作成イベントが発生した場合でも、.NET特定のスレッドの「親」または「子」通知できません
  12. 異なるデータ型に2つの異なる長さ属性、「長さ」と「カウント」があるという事実は、ささいな迷惑です。
  13. はWPFの貧弱な設計について永遠に続けることができました...そしてWCF(いくつかのシナリオでは非常に便利ですが)も疣贅でいっぱいです。一般に、BCLの新しいサブライブラリの多くの肥大化、直感的でない、および限られたドキュメントにより、私はそれらを使用することを躊躇します。新しいものの多くは、はるかに単純で、小さく、使いやすく、理解しやすく、疎結合で、文書化が進んでおり、より多くのユースケースに適用でき、より速く、より強く型付けされている可能性があります。
  14. プロパティゲッターとセッターの間の不必要な結合にしばしば悩まされます。派生クラスまたは派生インターフェイスでは、基本クラスまたは基本インターフェイスにゲッターしかない場合、単純にセッターを追加することはできません。ゲッターをオーバーライドすると、セッターを定義できなくなります。セッターを仮想として定義することはできませんが、ゲッターを非仮想として定義することはできません。

私はのサブセットについて、あなたに同意しIList<T>、私が使用したいのに、IReadableByIndex<out T>IAppendable<in T>。あなたの他のものの多くは私も同意するスコークです。
スーパーキャット2012

それは本当に長い名前です。たぶん私たちは妥協することができIListReader<T>ます;)-私は「シンク」(書き込み専用インターフェース)の反意語として「ソース」という言葉を使用します。
qwertie 2012

多分IListSource<in T>またはIReadableList<out T>。基本インターフェイスタイプに、すべての派生物に存在しないメソッドを含めることには価値がありますが、インターフェイスをある程度特殊化することはしばしば良いことだと思います。たとえば、機能IList<T>する場合と機能しない場合があるサイズ変更メソッドを含む、およびIResizableList<T>同じメソッドを実装するが、機能することを保証するを使用できます。このようなアプローチは、フィールドが可変リストへの唯一の現存する参照、または不変リストへの共有参照のいずれかを保持する可能性がある場合に役立つ可能性があります。
スーパーキャット2012

このような場合、リストの内容を変更したいコードは、それが可変タイプであるかどうかをチェックし、そうでない場合は、不変リストと同じアイテムを含む新しい可変インスタンスを生成して、それを使用し始めます。コードが変更メソッドを使用するたびにフィールドを常にタイプキャストする必要があるとしたら、それは面倒です。
スーパーキャット2012

@supercat C#は、インターフェイスが実装されていることを確認してすぐに使用するための本当に簡単な方法を提供していないため、これは面倒なことです。MSは、それを簡単にするために言語機能を追加する必要があります。私の好みのテクニックはバインディング式ですが、if (rl:(list as IResizableList<T>) != null) rl.Add(...);他の提案もあります。さまざまなコレクションとコレクションアダプターの作成者として、私を苛立たせているのは、例外をスローするダミーメソッドをたくさん書いていることです。型安全ファンとして、私は違法なメソッドを呼び出させたくありません。IntelliSenseファン、リストに表示されたくありません。
qwertie 2012

2

1.xで私を驚かせたのは、を使用するSystem.Xml.XmlValidatingReaderとき、ValidationEventHandler'sValidationEventArgsは、やのXmlSchemaExceptionようなすべての有用な情報を持つ基礎となる(内部としてマークされた)を公開しないことでした。代わりに、メッセージ文字列プロパティからこれを解析するか、リフレクションを使用してそれを掘り下げることが期待されています。よりサニタイズされたエラーをエンドユーザーに返したい場合は、あまり良くありません。linenumberposition


1

たとえば、ある列挙型の値を別の列挙型で使用できないのは気に入らないでしょう。

    enum Colors { white, blue, green, red, black, yellow }

    enum SpecialColors { Colors.blue, Colors.red, Colors.Yellow } 

2
しかし、これは意味がありません。 typeof(Color)!= typeof(SpecialColors)
Kirk Woll

10
行うのは簡単です:enum SpecialColors { blue = Colors.blue, red = Colors.red, yellow = Colors.Yellow }
Trystan Spangler 2011

0

暗黙的に型指定された変数は、IMOの実装が不十分でした。実際にはLinq式を操作する場合にのみ使用する必要があることはわかっていますが、ローカルスコープ外で宣言できないのは面倒です。

MSDNから:

  • varは、ローカル変数が同じステートメントで宣言および初期化されている場合にのみ使用できます。変数をnull、メソッドグループ、無名関数に初期化することはできません。
  • varは、クラススコープのフィールドでは使用できません。
  • varを使用して宣言された変数は、初期化式では使用できません。言い換えると、この式は有効です。inti =(i = 20); ただし、この式はコンパイル時エラーを生成します。vari =(i = 20);
  • 複数の暗黙的に型指定された変数を同じステートメントで初期化することはできません。
  • varという名前の型がスコープ内にある場合、varキーワードはその型名に解決され、暗黙的に型指定されたローカル変数宣言の一部として扱われません。

実装が不十分だと思う理由は、彼らがそれをvarと呼んでいるからですが、それはバリアントになるにはほど遠いです。これは、完全なクラス名を入力する必要がないための単なる省略構文です(Linqで使用する場合を除く)


暗黙的に型付けされていない(var)、明らかに匿名型(new {...})
明らかに匿名

私が投稿したものを読み直してください、そしてそれは間違っていました。私は暗黙的に型付けされた変数を意味しました
lomaxx 2009年

1
Eric Lippertは、varをメソッドの外で使用できない理由を説明しました。これは、基本的に、可能性のブラックボックスを作成するためです。 blogs.msdn.com/ericlippert/archive/2009/01/26/...
Guvante

1
varはバリアントになることを意図していません!それは正確に速記用です(特にアノンタイプ)。それがやってくるときダイナミックをお楽しみください...
ShuggyCoUk
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.