3

私は API を C から C# に変換しています。関数の 1 つは、多数の関連オブジェクトを割り当てます。そのうちのいくつかはオプションです。C バージョンは、オブジェクトに整数ハンドルを返すために使用されるいくつかのポインター パラメーターを受け入れます。呼び出し元は、NULLこれらのオブジェクトの割り当てを回避するために、いくつかのポインターを渡すことができます。

void initialize(int *mainObjPtr, int *subObjPtr, int *anotherSubObjPtr);

initialize(&mainObj, &subObj, NULL);

C# バージョンの場合、明らかな変換ではout、ポインターの代わりにパラメーターが使用されます。

public static void Initialize(out int mainObj, out int subObj,
    out int anotherSubObj);

...しかし、これでは、どのオブジェクトが不要であるかを示す方法がありません。私が真似できるような、C# API のよく知られた例はありますか? そうでない場合、何か提案はありますか?

4

3 に答える 3

3

intまあ、とにかくオブジェクトに使用するべきではありません-それらは参照である必要がありますout SomeMainType mainObj, out SomSubType subObj。これで、オーバーロードを使用できますが、これは不自然です。

より良いアプローチは、3つのオブジェクト(カスタムタイプ、または.NET 4.0ではタプル)で何かを返すことです。

何かのようなもの:

class InitializeResult {
    public SomeMainType MainObject {get;set;}
    public SomeSubType SubObject {get;set;}
    ...
}
public static InitializeResult Initialize() {...}

それを読み直すと、呼び出し元もデータを渡しているように見えます null / not-nullのみであっても)ので、正しいオプションoutではありませんでした。多分旗の列挙型?

[Flags]
public enum InitializeOptions {
    None = 0, Main = 1, Sub = 2, Foo = 4, Bar = 8, ..
}

と電話:

var result = Initialize(InitializeOptions.Main | InitializeOptions.Sub);
var main = result.MainObject;
var sub = result.SubObject;
于 2010-06-13T07:47:25.653 に答える
2

最も近い翻訳は、とを使用することrefですIntPtr

public static void Initialize(ref IntPtr mainObj, ref IntPtr subObj,
ref IntPtr anotherSubObj)

IntPtr.Zero不要な値を指定します。

しかし、私にとっては、P/Invoke 署名を理解しようとしているのでない限り、なぜ閉じる API に似せたいのかという疑問が生じます。mainObj次のような両方のサブオブジェクトへのアクセス可能な参照があると仮定します

public static MainObjectType Initialize(bool initSubObj, bool initAnotherSubObj)

私にははるかにクリーンなソリューションのようです。.NET 4 では、ブール引数をオプションにすることも、.NET 4 以前のオーバーロードでこれをシミュレートすることもできます。サブ オブジェクトへのアクセス可能な参照がない場合は、参照を保持する単純なコンテナー型を返すことができます。

于 2010-06-13T07:51:05.973 に答える
0

パラメータを取り出さないメソッドのオーバーロードを提供し、それを行うオーバーロードを呼び出すことができます:

public static void Initialize()
{
    int mainObj;
    int subObj;
    int anotherSubObj;
    Initialize(out mainObj, out subObj, out anotherSubObj);
    // discard values of out parameters...
}

public static void Initialize(out int mainObj, out int subObj, out int anotherSubObj)
{
    // Whatever...
}

しかし、Marc が提案したように、おそらくよりオブジェクト指向のアプローチを使用することを検討する必要があります...

于 2010-06-13T12:27:23.063 に答える