泥庭

2015年7月22日

【C#6.0】nameof

Filed under: .NET, C# — タグ: , — yone64 @ 12:09 PM
シリーズものが続かないBlogですが、第2回。
今度はnameofを見ていきます。

nameofって何?
変装や、クラス、メソッド、プロパティなどの名前(識別子)を文字列として取得できる演算子です。
何が嬉しいの?
プログラム内に直接文字列で指定するのと違って、リファクタリングなどの名前変更の恩恵にあずかれることです。
# これがしたいがために、これまではExpressionなどを駆使してました。

ということで、どういう使い方ができるか見てみましょう。
class Program
{
    static void Main(string[] args)
    {
        // 名前空間を取得
        // System
        Console.WriteLine(nameof(System));
        // 一番下の階層のみ取得できる
        // Reflection
        Console.WriteLine(nameof(System.Reflection));

        // クラス名を取得
        // Hoge
        Console.WriteLine(nameof(Hoge));
        // 名前空間で修飾してもクラス名のみ
        // ArrayList
        Console.WriteLine(nameof(System.Collections.ArrayList));
        // Genericの型引数は取得されない
        // List
        Console.WriteLine(nameof(System.Collections.Generic.List<int>));
        // だからと言って省略するとコンパイルエラー
        //Console.WriteLine(nameof(System.Collections.Generic.List<>));

        // Innerクラスの場合、取得できるのは内部クラスのみ
        // Fuga
        Console.WriteLine(nameof(Hoge.Fuga));
        // structでも同様
        // Hoge2
        Console.WriteLine(nameof(Hoge2));
        // interfaceでも同様
        // IHoge
        Console.WriteLine(nameof(IHoge));
        // enumも
        // Piyo
        Console.WriteLine(nameof(Piyo));

        // 各メンバ名を取得
        // インスタンスメンバでも、staticメンバでも、クラス修飾のあとに呼び出し可能
        // MyProperty
        Console.WriteLine(nameof(Hoge.MyProperty));
        // MyProperty1
        Console.WriteLine(nameof(Hoge.MyProperty1));
        // メソッド名を取得する際は括弧不要
        // Method2
        Console.WriteLine(nameof(Hoge.Method2));

        // 変数からも取得可能
        var n = new Hoge();
        // MyProperty
        Console.WriteLine(nameof(n.MyProperty));
        // インスタンス化する必要はない(実際に呼び出すわけではないので、NullReferenceExceptionは発生しない)
        var n2 = default(Hoge);
        // Property2
        Console.WriteLine(nameof(n2.Property2));
        // ただし、nameofの内部で初期化したり、default(Hoge)を使用したりすることはできない
        //Console.WriteLine(nameof(new Hoge().Property2));
        //Console.WriteLine(nameof(default(Hoge).Property2));
        // Method
        Console.WriteLine(nameof(n.Method));
        // Enumのメンバも同様に取得可能
        Console.WriteLine(nameof(Piyo.Piyo1));
        
        // プロパティーおよびフィールドは順番にたどっていくことが出来る
        // Name
        Console.WriteLine(nameof(n2.Property2.MyProperty.Name));
        // クラス修飾の後だと、再帰的にたどることはできない。
        //Console.WriteLine(nameof(Hoge.Property2.MyProperty.Name));
        // 途中にメソッドを挟むこともできない
        //Console.WriteLine(nameof(n2.Method2().MyProperty.Name));
        // 直接クラスを指定するのが自然なので、問題にはならないと思う。
        // Name
        Console.WriteLine(nameof(Hoge.Fuga.Piyo.Name));

        // 引数
        // args
        Console.WriteLine(nameof(args));

        // 変数
        // n
        Console.WriteLine(nameof(n));
    }
}

class Hoge
{
    public class Fuga
    {
        public Piyo MyProperty;
        public class Piyo
        {
            public string Name { get; set; }
        }
    }

    public int MyProperty { get; set; }

    public static int MyProperty1 { get; set; }

    public void Method() { }

    public Fuga Property2 { get; set; }

    public Fuga Method2() => null;
}

struct Hoge2 { }
interface IHoge { }

enum Piyo { Piyo1, Piyo2 }
概ね直観的な使い方が出来そうです。
# インスタンスメンバをクラス修飾から呼び出したり、メソッドを挟むことが出来なかったり、ジェネリックの扱いが微妙だったり
# ってあたりは、ちょっと??ってなりますが、すぐ慣れるでしょう

あと、nameofは同名のメソッドが定義可能で、挙動を上書きできてしまうので注意しましょう。
# 悪意しかない…
static void Main(string[] args)
{
    // dummy と表示される
    Console.WriteLine(nameof(DateTime.Now));
}

public static string nameof(object o) => "dummy";
広告

コメントする »

まだコメントはありません。

RSS feed for comments on this post. TrackBack URI

コメントを残す

以下に詳細を記入するか、アイコンをクリックしてログインしてください。

WordPress.com ロゴ

WordPress.com アカウントを使ってコメントしています。 ログアウト / 変更 )

Twitter 画像

Twitter アカウントを使ってコメントしています。 ログアウト / 変更 )

Facebook の写真

Facebook アカウントを使ってコメントしています。 ログアウト / 変更 )

Google+ フォト

Google+ アカウントを使ってコメントしています。 ログアウト / 変更 )

%s と連携中

WordPress.com Blog.

%d人のブロガーが「いいね」をつけました。