3

我正在将 API 从 C 转换为 C#,其中一个函数分配了许多相关对象,其中一些是可选的。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() {...}

重新阅读它,看起来调用者也在传递数据即使只有空/非空),所以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

最接近的翻译是使用refIntPtr

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

并指定IntPtr.Zero不需要的值。

但对我来说,问题是为什么你想要类似于关闭的 API,除非你试图找出 P/Invoke 签名。假设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...
}

但正如马克所建议的那样,您可能应该考虑使用更面向对象的方法......

于 2010-06-13T12:27:23.063 回答