c# - 親フォーム - wpf 画面 ロック




C#の非表示機能 (20)

これは、 この質問から次のことを学んだ後に思い浮かびました。

where T : struct

私たちC#開発者は皆、C#の基本を知っています。 宣言、条件、ループ、演算子などを意味します。

私たちの中には、 Generics匿名型lambdasLINQなどのようなものを習得した人もいます。

しかし、C#のファン、常習者、専門家でさえほとんど知らないC#の最も隠れた機能やトリックは何ですか?

これまでに明らかにされた機能は次のとおりです。


キーワード

属性

構文

  • ?? (合体ヌル)演算子by kokos
  • Nick Berardiによる番号のフラグ
  • where T:new LarsMæhlumによるwhere T:new
  • Keithによる暗黙のジェネリック
  • Keithによる1パラメーターラムダ
  • Keithによる自動プロパティ
  • Keithによる名前空間エイリアス
  • Patrickよる@を使用した逐語的文字列リテラル
  • lfoustによるenum
  • @variablenames by marxidad
  • marxidadによるeventオペレーター
  • Portmanによる文字列ブラケットのフォーマット
  • xanadontによるプロパティアクセサアクセシビリティ修飾子
  • JasonSによる条件付き(三項)演算子( ?: JasonS
  • Binoj Antonyによるcheckedおよびunchecked演算子
  • Floryによるimplicit and explicit演算子

言語機能

Visual Studioの機能

  • Himadriによるエディターでのテキストブロックの選択
  • DannySmurfスニペット

枠組み

メソッドとプロパティ

  • String.IsNullOrEmpty()メソッド
  • List.ForEach()メソッド
  • Will Deanの BeginInvoke()EndInvoke()メソッド
  • Nullable<T>.HasValueおよびNullable<T>.Valueプロパティ
  • John SheehanによるGetValueOrDefaultメソッド

ヒントとコツ

  • Andreas HR Nilssonによるイベントハンドラーのニースメソッド
  • Johnによる大文字の比較
  • dpによるリフレクションなしの匿名型へのアクセス
  • Willによってコレクションプロパティを遅延インスタンス化する簡単な方法
  • roosteronacid JavaScriptのような匿名インライン関数

その他


@は、文字列内のエスケープ文字を無視するようコンパイラーに指示します。

これを明確にしたかっただけです...エスケープ文字を無視するように指示するのではなく、実際にコンパイラに文字列をリテラルとして解釈するように指示します。

あなたが持っている場合

string s = @"cat
             dog
             fish"

実際には次のように出力されます(インデントに使用される空白も含まれていることに注意してください)。

cat
             dog
             fish

C#経由のCLRから

文字列を正規化する場合、 Microsoftは大文字比較を実行するためのコードを最適化したため、ToLowerInvariantではなくToUpperInvariantを使用することを強くお勧めします。

同僚がいつも比較する前に文字列を大文字に変更したことを覚えています。 最初に小文字に変換する方が「自然」だと思うので、なぜ彼がそうするのかといつも不思議に思っていました。 今本を読んだ後、私は理由を知っています。


  1. ??-合体演算子
  2. using(statement / directive)-Disposeの呼び出し以外にも使用できる優れたキーワード
  3. readonly -さらに使用する必要がありreadonly
  4. netmodules-Visual Studioにサポートがないのは残念です

C#(.NET 3.5)の最も評価が低く知名度の低い機能の1つは、 特に GenericsおよびLambdasと組み合わせた場合のExpression Treeです。 これは、NInjectやMoqなどの新しいライブラリが使用しているAPI作成のアプローチです。

たとえば、メソッドをAPIに登録し、そのAPIがメソッド名を取得する必要があるとしましょう

このクラスが与えられた場合:

public class MyClass
{
     public void SomeMethod() { /* Do Something */ }
}

以前は、開発者が文字列と型(または主に文字列ベースの何か)でこれを行うのを見るのは非常に一般的でした:

RegisterMethod(typeof(MyClass), "SomeMethod");

まあ、それは強い型付けの欠如のために残念です。 「SomeMethod」の名前を変更するとどうなりますか? ただし、3.5では、厳密に型指定された方法でこれを実行できます。

RegisterMethod<MyClass>(cl => cl.SomeMethod());

RegisterMethodクラスは、次のようにExpression<Action<T>>使用します。

void RegisterMethod<T>(Expression<Action<T>> action) where T : class
{
    var expression = (action.Body as MethodCallExpression);

    if (expression != null)
    {
        // TODO: Register method
        Console.WriteLine(expression.Method.Name);
    }
}

これが、私が今ラムダと式ツリーを愛している大きな理由の1つです。


yield 」が思い浮かぶでしょう。 DefaultValueAttributeなどの属性のいくつかもお気に入りです。

var 」キーワードはもう少し知られていますが、.NET 2.0アプリケーションでも使用できること( .NET 3.5コンパイラ使用して 2.0コードを出力するように設定している限り)はあまり知られていないようです。まあ。

編集:ココ、??を指摘してくれてありがとう 演算子、それは実際に非常に便利です。 それをグーグルするのは少し難しいので(??は無視されます)、その演算子のMSDNドキュメントページは次のとおりです: ?? ??


「as」キーワードをかなり長い間知りませんでした。

MyClass myObject = (MyClass) obj;

MyClass myObject = obj as MyClass;

2番目は、objがMyClassでない場合、クラスキャスト例外をスローするのではなく、nullを返します。


nullイベントハンドラーのチェックを避ける

宣言時にイベントに空のデリゲートを追加することで、イベントを呼び出す前に常にnullをチェックする必要がなくなります。 例:

public delegate void MyClickHandler(object sender, string myValue);
public event MyClickHandler Click = delegate {}; // add empty delegate!

やってみましょう

public void DoSomething()
{
    Click(this, "foo");
}

これの代わりに

public void DoSomething()
{
    // Unnecessary!
    MyClickHandler click = Click;
    if (click != null) // Unnecessary! 
    {
        click(this, "foo");
    }
}

また、このトピックに関するEric Lippertの関連する議論とこのブログ投稿も参照してください(および可能性のある欠点)。


ラムダと型推論は過小評価されています。 ラムダは複数のステートメント持つことができ 、次のように、互換性のあるデリゲートオブジェクトとして自動的に二重になります(署名が一致することを確認するだけです)。

Console.CancelKeyPress +=
    (sender, e) => {
        Console.WriteLine("CTRL+C detected!\n");
        e.Cancel = true;
    };

new CancellationEventHandlerなく、 sendereタイプを指定する必要がないことに注意してください。これらはイベントから推測できます。 これが、 delegate (blah blah)全体delegate (blah blah)を記述するのに面倒なことではなく、パラメーターのタイプを指定する必要がある理由です。

ラムダは何も返す必要がなく 、型推論はこのようなコンテキストでは非常に強力です。

ところで、関数型プログラミングの意味でラムダを作るラムダをいつでも返すことができます。 たとえば、Button.Clickイベントを処理するラムダを作成するラムダは次のとおりです。

Func<int, int, EventHandler> makeHandler =
    (dx, dy) => (sender, e) => {
        var btn = (Button) sender;
        btn.Top += dy;
        btn.Left += dx;
    };

btnUp.Click += makeHandler(0, -1);
btnDown.Click += makeHandler(0, 1);
btnLeft.Click += makeHandler(-1, 0);
btnRight.Click += makeHandler(1, 0);

連鎖に注意してください: (dx, dy) => (sender, e) =>

これが関数型プログラミングクラスを受講できてうれしい理由です。

Cのポインター以外に、それはあなたが学ぶべき他の基本的なことだと思います:-)


String.Format式内で中括弧を使用しようとしている場合...

int foo = 3;
string bar = "blind mice";
String.Format("{{I am in brackets!}} {0} {1}", foo, bar);
//Outputs "{I am in brackets!} 3 blind mice"

これはC#そのものではありませんが、 System.IO.Path.Combine()を実際に使用している人は見たことがありません。 実際、Pathクラス全体は本当に便利ですが、 誰も使用してません!

すべての製品版アプリには次のコードが含まれている必要があります。

string path = dir + "\\" + fileName;

その他すべて

1)暗黙的なジェネリック(クラスではなくメソッドのみが必要な理由)

void GenericMethod<T>( T input ) { ... }

//Infer type, so
GenericMethod<int>(23); //You don't need the <>.
GenericMethod(23);      //Is enough.

2)1つのパラメーターを持つ単純なラムダ:

x => x.ToString() //simplify so many calls

3)匿名型と初期化子:

//Duck-typed: works with any .Add method.
var colours = new Dictionary<string, string> {
    { "red", "#ff0000" },
    { "green", "#00ff00" },
    { "blue", "#0000ff" }
};

int[] arrayOfInt = { 1, 2, 3, 4, 5 };

別のもの:

4)自動プロパティには異なるスコープを設定できます。

public int MyId { get; private set; }

思い出させてくれてありがとう@pzycoman:

5)名前空間エイリアス(この特定の区別が必要になる可能性が高いというわけではありません):

using web = System.Web.UI.WebControls;
using win = System.Windows.Forms;

web::Control aWebControl = new web::Control();
win::Control aFormControl = new win::Control();

エイリアス化されたジェネリック:

using ASimpleName = Dictionary<string, Dictionary<string, List<string>>>;

Dictionary<string, Dictionary<string, List<string>>>代わりにASimpleNameを使用できます。

多くの場所で同じ汎用の長くて複雑なものを使用する場合に使用します。


ジェネリック型の「デフォルト」キーワード:

T t = default(T);

Tが参照型の場合は「null」、intの場合は0、booleanの場合はfalseなどになります。


メソッドから匿名型を返し、リフレクションなしでメンバーにアクセスします。

// Useful? probably not.
private void foo()
{
    var user = AnonCast(GetUserTuple(), new { Name = default(string), Badges = default(int) });
    Console.WriteLine("Name: {0} Badges: {1}", user.Name, user.Badges);
}

object GetUserTuple()
{
    return new { Name = "dp", Badges = 5 };
}    

// Using the magic of Type Inference...
static T AnonCast<T>(object obj, T t)
{
   return (T) obj;
}

文書化されていないC#キーワードの形式で、いくつかの興味深い隠されたC#機能を以下に示します。

__makeref

__reftype

__refvalue

__arglist

これらは文書化されていないC#キーワードであり(Visual Studioでも認識されます!)、ジェネリックの前により効率的なボクシング/アンボクシングのために追加されました。 System.TypedReference構造体と連携して動作します。

可変長パラメーターリストに使用される__arglistもあります。

人々があまり知らないことの1つはSystem.WeakReferenceです。これは、オブジェクトを追跡しながら、ガベージコレクターがそれを収集できるようにする非常に便利なクラスです。

最も有用な「隠された」機能は、yield returnキーワードです。 それは本当に隠されていませんが、多くの人々はそれについて知りません。 LINQはこの上に構築されています。 フードの下でステートマシンを生成することにより、遅延実行クエリを可能にします。 Raymond Chenは最近、 内部のざらざらした詳細について投稿しました。


正規表現とファイルパスに便利なものを次に示します。

"c:\\program files\\oldway"
@"c:\program file\newway"

@は、文字列内のエスケープ文字を無視するようコンパイラーに指示します。


私のお気に入りのトリックは、 null合体演算子と括弧を使用して、コレクションを自動的にインスタンス化することです。

private IList<Foo> _foo;

public IList<Foo> ListOfFoo 
    { get { return _foo ?? (_foo = new List<Foo>()); } }

私は、ほとんどのC#開発者が「nullable」型について知らないことに気付く傾向があります。 基本的に、null値を持つことができるプリミティブ。

double? num1 = null; 
double num2 = num1 ?? -100;

null許容のdouble num1をnullに設定してから、通常のdouble num2num1に設定します。num1がnullの場合は-100に設定します。

http://msdn.microsoft.com/en-us/library/1t3y8s4s(VS.80).aspx

Nullable型に関するもう1つのこと:

DateTime? tmp = new DateTime();
tmp = null;
return tmp.ToString();

String.Emptyを返します。 詳細については、 thisリンクを確認してください


@エド、私はこれを投稿することについて少し黙っています。ただし、コードサンプルでは次のように指摘します。

MyClass c;
  if (obj is MyClass)
    c = obj as MyClass

「is」を使用する場合、「as」を使用して安全なキャストでフォローアップするのはなぜですか?objが本当にMyClassであることを確認した場合、沼地の標準キャストです:

c = (MyClass)obj

...失敗することはありません。

同様に、あなたはただ言うことができます:

MyClass c = obj as MyClass;
if(c != null)
{
   ...
}

確かに.NETの内部については十分に知りませんが、私の直感では、これにより最大2つの型キャスト操作が最大1つに削減されることを教えてくれます。どちらにしても処理銀行を破ることはほとんどありません。個人的には、後者のフォームもきれいに見えると思います。


ミックスイン。基本的に、複数のクラスに機能を追加したいが、すべてのクラスに1つの基本クラスを使用できない場合は、各クラスに(メンバーのない)インターフェイスを実装させます。次に、インターフェイスの拡張メソッド記述します

public static DeepCopy(this IPrototype p) { ... }

もちろん、ある程度の明瞭さが犠牲になります。しかし、それは機能します!





hidden-features