5

C ++には__FUNCTION__、マクロが使用されている関数名の文字列リテラルにコンパイルされるなどの事前定義されたマクロがあります。

void MyFunc()
{
    printf("I'm in %s!", __FUNCTION__); // I'm in MyFunc!
}

C#に似たものはありますか?私はasp.netWebフォームに対してこれを行うことを探しています:

public string MyProperty
{
    get { return (string)ViewState[__PROPERTY__]; }
    set { ViewState[__PROPERTY__] = value; }
}

明らかにこれは機能しません(そうでなければ私は質問しません)、文字列リテラルを使用する場合と比較して、リフレクションを使用しない、またはパフォーマンスに悪影響を与えるC#に類似したものがあるかどうかを知りたいです"MyProperty"

これにより、私の側のタイプミスが減ることを願っていますが、これが役立つ他のいくつかの例を考えることができます。

4

3 に答える 3

5

C# のプリプロセッサは、C++ のような関連付けられた値を持つマクロをサポートしていませんが、コンパイラが生成したCaller Informationを介して、C# 5.0 以降 (少なくとも VS2012+) をサポートするコンパイラで実行できます。具体的には、System.Runtime.CompilerServices名前空間のCallerMemberNameAttributeを使用します。質問のコードに基づいて、次の例を作成して、やりたいことを実行する方法を説明しました。

using System;

class ViewState
{
    public string this[string propertyName]
    {
        get { return propertyName; }
        set { }
    }
};
class View
{
    ViewState mState = new ViewState();

    static string GetCallerName(
        [System.Runtime.CompilerServices.CallerMemberName] string memberName = "")
    {
        return memberName;
    }

    public string MyProperty
    {
        get { return (string)mState[GetCallerName()]; }
        set { mState[GetCallerName()] = value; }
    }
};
class Program
{
    static void Main(string[] args)
    {
        var view = new View();
        Console.WriteLine(view.MyProperty);

        Console.ReadKey();
    }
};

「MyProperty」がコンソールに出力されます。コンパイル時に、コンパイラは GetCallerName の memberName 引数のデフォルト値を呼び出し側の構成 (プロパティ、メソッドなど) の名前に置き換えます。そのため、プログラマーによるコードのメンテナンスは必要ありません

また、これには、難読化ツールがコンパイル後に行われる限り、難読化ツールとうまく連携できるという追加の利点があることにも注意してください。

于 2014-02-28T03:40:09.757 に答える
3

StackTrace と StackFrameを使用して、現在のメソッドの名前を取得できます

StackTrace st = new StackTrace(); 
StackFrame sf = st.GetFrame(1);
string method = sf.GetMethod().ToString();

プロパティの場合、返されるメソッド名にはマジックget_またはset_プレフィックスが含まれます。

ただし、これを C++ のようにインライン マクロまたは関数に実際にリファクタリングできるとは思いません。しかし、これを DRY するためにユーティリティ メソッドをリファクタリングする場合、おそらく StackTrace を 1 ステップ戻して、呼び出し元の情報をログに記録できますか?

于 2012-10-31T14:25:49.930 に答える
1

ViewBagASP.NET WebForms にa のようなものがあるかどうかはわかりません。ない場合に備えて、所有するのは難しくありません。その後、そのクラスで をラップしてViewState、必要に応じて通常のプロパティ メンバー アクセスを取得できます。

public class ExpandoViewState : DynamicObject
{
    private readonly StateBag _viewState;

    public ExpandoViewState(StateBag viewState)
    {
        _viewState = viewState;
    }

    public override bool TryGetMember(GetMemberBinder binder, out object result)
    {
        result = _viewState[binder.Name];
        if (result != null)
            return true;
        return base.TryGetMember(binder, out result);
    }

    public override bool TrySetMember(SetMemberBinder binder, object value)
    {
        _viewState[binder.Name] = value;
        return true;
    }
}

...

dynamic state = new ExpandoViewState(ViewState);
var val = (string)state.MyProperty;
state.MyProperty = "hi";
于 2012-10-31T14:35:43.390 に答える