6

C#でこれを行うためのエントリがたくさんありますが、C++では何もありません

一部のマネージC++コードには、C#部分とc++部分の間でデータを渡すために使用される一連のプロパティがあります。C#側では、ここに示されている答えは非常にうまく機能しているので、C++と同様のことをしたいと思います。リンクに含まれるソリューションのコピー:

string NameOf<T>(Expression<Func<T>> expr) {
    return ((MemberExpression) expr.Body).Member.Name;
}

var gmtList = new SelectList(repository.GetSystemTimeZones(),
    NameOf(() => tz.Id),
    NameOf(() => tz.DisplayName));

私の問題は、呼び出しの正しい構文、具体的には次のセクションを取得できないように見えることです。

() => tz.DisplayName

C ++でこれを行う方法を説明するリソースをオンラインで見つけることができないようです。そのため、誰かが経験やリンクを持っている場合は、助けていただければ幸いです。

4

3 に答える 3

6

私はこれらすべてのラムダとクールなSystem::Linq名前空間(CLinqライブラリなどを含む)に数時間苦労し、それから...私はただ考えました:純粋に静的な決定を使用しないのはなぜですか?

宣言するだけです

/// Convert X to "X", the classical preprocessing trick
#define GetPropName(TheClassName, ThePropertyName) #ThePropertyName

そして私達はすることができます

Console::WriteLine( GetPropName(TimeZone, Id) );

画面に「Id」を印刷します。

ええ...今、興味深い部分です。型安全。このソリューションについてコメントストームが発生していると聞きました(「いいえ!これは良くありません。ThePropertyNameがクラスにあるかどうかはチェックされません!」)

わかった。解決策:ダミーのTheClassNameのインスタンスでThePropertyNameを使用するマクロを使用して、意味のないコードを生成しましょう。

/// This macro will produce the compilation error if ThePropertyName is not in the class named TheClassName
#define CheckForPropertyExistence(TheClassName, ThePropertyName) \
/* Create an array of Objects which will be converted to string and ignored*/ \
(gcnew array<System::Object^> { (gcnew TheClassName())->ThePropertyName })->ToString()

/// We get the property name using the "dinosaur strategy" - good old macro concatenated with the empty string which in turn is formed in CheckFor() macro
#define GetPropertyName(TheClassName, ThePropertyName) \
(gcnew System::String(#ThePropertyName)) + CheckForPropertyExistence(TheClassName, ThePropertyName)->Substring(0,0)

これで、完全なサンプルを提供できます。

using namespace System;

/// Sample class
public ref class TheTimeZone
{
public:
    TheTimeZone()
    {
        _Id = 0;
        _DisplayName = "tmp";
    }

    property int Id
    {
    public:
        int get() {return _Id;}
        void set(int v) { _Id = v; }
    }

    property String^ DisplayName
    {
    public:
        String^ get() { return _DisplayName; }
        void set(String^ v) { _DisplayName = v; }
    }

private:
    int _Id;
    String^ _DisplayName;
};

/// This macro will produce the error if ThePropertyName is not in the class named TheClassName
#define CheckForPropertyExistence(TheClassName, ThePropertyName) \
/* Create an array of Objects which will be converted to string and ignored*/ \
(gcnew array<System::Object^> { (gcnew TheClassName())->ThePropertyName })->ToString()

/// We get the property name using the "dinosaur strategy":
/// good old macro concatenated with the empty string
/// which in turn is formed in CheckFor() macro
#define GetPropertyName(TheClassName, ThePropertyName) \
(gcnew System::String(#ThePropertyName)) + \
CheckForPropertyExistence(TheClassName, ThePropertyName)->Substring(0,0)

/// To get properties from objects with no default constructor
#define GetPropertyNameForObject(TheObject, ThePropertyName) \
(gcnew System::String(#ThePropertyName)) + \
(gcnew array<System::Object^> { (TheObject)-> ThePropertyName })->ToString()->Substring(0,0)

/// Test for our macros
int main(array<System::String ^> ^args)
{
    /// Prints "Length"
    /// We cannot use default constructor here
    Console::WriteLine(GetPropertyNameForObject (gcnew System::String("test"), Length) );

    /// Prints "Id"
    Console::WriteLine(GetPropertyName (TheTimeZone, Id) );

/// Uncomment and get the error
    //Console::WriteLine(GetPropertyName (TheTimeZone, Id23) );

    return 0;
}
于 2012-05-21T19:09:41.557 に答える
2

C#のラムダ式はデリゲートのシンタックスシュガーであるため、C ++ / CLIで同じ機能を使用できるようにするには、ラムダ式に相当するデリゲートを見つける必要があります。

生活を少し楽にするために、Linq用のC ++ / CLIラッパーを提供するCLinq(「ラムダ式」セクションを参照)を調べることができます。

:C ++ 11ラムダ式とC#ラムダ式を混同しないでください。前者はネイティブコードでのみサポートされます。C ++ 11ラムダを使用することは可能ですが、デリゲートを提供するためにいくつかの追加作業を行う必要があります(このCodeProjectの記事では主題について説明しています)

于 2012-05-16T11:12:03.187 に答える
1

これは古いスレッドだと思いますが、次のようなものでも機能する可能性があります。

String^ NameOfSanityCheck(Object^ object, String^ name) { return name; } // could parse with a regex string like: "(->)|(::)|(\.)"

#define nameof(s) NameOfSanityCheck(s, #s)
于 2020-11-11T19:17:56.637 に答える