322

バージョン 6.0 には の新機能が追加nameofされましたが、変数名を取得してコンパイル時に文字列に変更するだけなので、その目的がわかりません。

使用時に何らかの目的があるのではないかと思いましたが、使用<T>しようとすると、使用されているタイプの代わりにnameof(T)a が出力されます。T

目的について何か考えはありますか?

4

17 に答える 17

377

プロパティ名に基づいて例外をスローしたり、イベントを処理したりする場合など、プロパティの名前を再利用したい場合はどうでしょうかPropertyChanged。物件名を記載したいケースが多いです。

次の例を見てください。

switch (e.PropertyName)
{
    case nameof(SomeProperty):
    { break; }

    // opposed to
    case "SomeOtherProperty":
    { break; }
}

最初のケースではSomeProperty、プロパティ定義と式の両方を変更しないと、名前を変更するとコンパイル エラーが発生しますnameof(SomeProperty)。2 番目のケースでは、文字列の名前を変更SomeOtherPropertyまたは変更する"SomeOtherProperty"と、ビルド時にエラーや警告が発生せずに、実行時の動作が暗黙のうちに壊れます。

これは、コードをコンパイルしてバグをなくす (一種の) ための非常に便利な方法です。

( Eric Lippert の非常に素晴らしい記事で、なぜ成功しinfoofなかったのか、成功したのかnameof)

于 2015-07-29T09:07:55.843 に答える
28

nameofC# 6.0 の機能が便利になるもう 1 つの使用例- DB の取得をより簡単にするDapperのようなライブラリを考えてみましょう。これは優れたライブラリですが、クエリ内でプロパティ/フィールド名をハードコーディングする必要があります。つまり、プロパティ/フィールドの名前を変更すると、新しいフィールド名を使用するようにクエリを更新するのを忘れる可能性が高くなります。文字列補間とnameof機能を使用すると、コードの保守がはるかに容易になり、タイプセーフになります。

リンクにある例から

名前なし

var dog = connection.Query<Dog>(
    "select Age = @Age, Id = @Id",
    new {Age = (int?) null, Id = guid});

名前付き

var dog = connection.Query<Dog>(
    $"select {nameof(Dog.Age)} = @Age, {nameof(Dog.Id)} = @Id",
    new {Age = (int?) null, Id = guid});
于 2016-11-16T01:57:35.547 に答える
14

私が考えることができる最も一般的な使用例は、INotifyPropertyChangedインターフェースを操作する場合です。(基本的に、WPF とバインディングに関連するすべてがこのインターフェイスを使用します)

次の例を見てください。

public class Model : INotifyPropertyChanged
{
    // From the INotifyPropertyChanged interface
    public event PropertyChangedEventHandler PropertyChanged;

    private string foo;
    public String Foo
    {
        get { return this.foo; }
        set
        {
            this.foo = value;
            // Old code:
            PropertyChanged(this, new PropertyChangedEventArgs("Foo"));

            // New Code:
            PropertyChanged(this, new PropertyChangedEventArgs(nameof(Foo)));           
        }
    }
}

古い方法でわかるように、変更されたプロパティを示すために文字列を渡す必要があります。nameofプロパティの名前を直接使用できます。これは大したことではないように思えるかもしれません。しかし、誰かがプロパティの名前を変更するとどうなるか想像してみてFooください。文字列を使用すると、バインドは機能しなくなりますが、コンパイラは警告しません。nameof を使用すると、 name のプロパティ/引数がないというコンパイラ エラーが発生しますFoo

一部のフレームワークはリフレクション マジックを使用してプロパティの名前を取得することに注意してください

于 2015-07-29T19:03:31.997 に答える
7

MSDN の記事には、MVC ルーティング (私にとってその概念を実際にクリックした例) がいくつか挙げられています。(フォーマットされた)説明の段落は次のとおりです。

  • コードのエラーを報告するときは、
  • モデル ビュー コントローラー (MVC) リンクの接続、
  • プロパティ変更イベントの発火など

メソッドの文字列名を取得したいことがよく あります。nameof を使用すると、定義の名前を変更するときにコードを有効に保つことができます。

以前は文字列リテラル を使用して定義を参照する必要がありましたが、ツールはこれらの文字列リテラルをチェックすることを認識していないため、コード要素の名前を変更するときに 脆弱でした。

受け入れられた/最高評価の回答は、すでにいくつかの優れた具体例を示しています。

于 2015-08-05T16:16:54.953 に答える
6

他の人がすでに指摘しているように、nameofオペレーターはソースコードで要素に付けられた名前を挿入します。

これは、この文字列リファクタリングを安全にするため、リファクタリングの点で非常に良いアイデアであることを付け加えたいと思います。以前は、同じ目的でリフレクションを利用する静的メソッドを使用していましたが、実行時のパフォーマンスに影響がありました。nameofオペレーターは実行時のパフォーマンスに影響を与えません。コンパイル時に機能します。コードを見るとMSIL、文字列が埋め込まれていることがわかります。次のメソッドとその逆アセンブル コードを参照してください。

static void Main(string[] args)
{
    Console.WriteLine(nameof(args));
    Console.WriteLine("regular text");
}

// striped nops from the listing
IL_0001 ldstr args
IL_0006 call System.Void System.Console::WriteLine(System.String)
IL_000C ldstr regular text
IL_0011 call System.Void System.Console::WriteLine(System.String)
IL_0017 ret

ただし、ソフトウェアの難読化を計画している場合、これは欠点になる可能性があります。難読化後、埋め込まれた文字列が要素の名前と一致しなくなる場合があります。このテキストに依存するメカニズムは壊れます。その例には、リフレクション、NotifyPropertyChanged ... などがありますが、これらに限定されません。

実行時に名前を決定するとパフォーマンスがいくらか低下しますが、難読化しても安全です。難読化が必要でも計画でもない場合は、nameofオペレーターを使用することをお勧めします。

于 2015-08-01T12:36:51.910 に答える
1

nameofこれにより、アプリケーション内の非常に長く複雑な SQL ステートメントの可読性が向上することがわかりました。これにより、変数が文字列の海から目立ち、変数が SQL ステートメントのどこで使用されているかを把握する作業が不要になります。

public bool IsFooAFoo(string foo, string bar)
{
    var aVeryLongAndComplexQuery = $@"SELECT yada, yada
    -- long query in here
    WHERE fooColumn = @{nameof(foo)}
    AND barColumn = @{nameof(bar)}
    -- long query here";


    SqlParameter[] parameters = {
        new SqlParameter(nameof(foo), SqlDBType.VarChar, 10){ Value = foo },
        new SqlParameter(nameof(bar), SqlDBType.VarChar, 10){ Value = bar },
    }
}
于 2020-01-16T17:21:30.903 に答える
0

nameofキーワードの使用法の 1 つは、プログラムBindingで wpfに設定することです。

設定するには文字列で設定する必要があり、Bindingキーワードを使用すると、Refactor オプションを使用できます。Pathnameof

たとえば、 にIsEnable依存関係プロパティがUserControlあり、それを にバインドする場合IsEnableCheckBoxUserControl次の 2 つのコードを使用できます。

CheckBox chk = new CheckBox();
Binding bnd = new Binding ("IsEnable") { Source = this };
chk.SetBinding(IsEnabledProperty, bnd);

CheckBox chk = new CheckBox();
Binding bnd = new Binding (nameof (IsEnable)) { Source = this };
chk.SetBinding(IsEnabledProperty, bnd);

最初のコードはリファクタリングできないのは明らかですが、2番目のコードは...

于 2016-07-17T23:58:18.097 に答える