简体   繁体   English

通过单个功能“使用”多个IDisposable

[英]“using” multiple IDisposables from a single function

I have a method that returns a NativeList<> of structs AStruct , where NativeList<> is a wrapper over unmanaged memory that implements IDisposable . 我有一个返回结构AStructNativeList<>AStruct ,其中NativeList<>是实现IDisposable非托管内存的包装。 AStruct contains another pointer backed by a NativeList<float> also created in the same method, so: AStruct包含另一个由NativeList<float>支持的指针,该指针也以相同的方法创建,因此:

private unsafe NativeList<AStruct> GetAStructs()
{
    var floatList = new NativeList<float>();
    floatList.Add(0.0f);

    var list = new NativeList<AStruct>();

    AStruct a1 = new AStruct();
    a1.floats = (float*)floatList.Data;
    list.Add(a1);

    // ...

    return list;
}

This is a problem because now floatList is not referenced anymore after calling GetAStructs() . 这是一个问题,因为现在floatList不再被调用后参考GetAStructs() So I've changed the method signature to include an out parameter. 因此,我更改了方法签名以包括out参数。

private unsafe NativeList<AStruct> GetAStructs(out IDisposable toDispose)
{
    // ...

    toDispose = floatList;
    return list;
}

And I'm calling it like this 我这样称呼它

using (NativeList<AStruct> disposableList = GetAStructs(out IDisposable toDispose))
using (toDispose)
{
    callNativeFunction((AStruct*)disposableList.Data);
}

Will this work as intended? 这会按预期工作吗? Is there a way to do this without exposing an implementation detail to the calling method? 有没有办法在不将实现细节暴露给调用方法的情况下做到这一点?

I'll admit I don't know much about NativeArray, but in cases like this you can often get the functionality you need by creating a subclass of the class you're working with. 我承认我对NativeArray不太了解,但是在这种情况下,通常可以通过创建要使用的类的子类来获得所需的功能。

In this case, I'd suggest you create a subclass of NativeList that includes a callback for disposal. 在这种情况下,建议您创建一个NativeList的子类,其中包括要处理的回调。 Pass it a function that will do the work that you were previously asking the caller to do. 向其传递一个函数,该函数将完成您之前要求调用者执行的工作。

Example subclass: 子类示例:

class MyNativeList<T> : NativeList<T>
{
    protected readonly Action _callAfterDisposal;

    public MyNativeList(Action callAfterDisposal) : base()
    {
        _callAfterDisposal= callAfterDisposal;
    }

    public override Dispose()
    {
        base.Dispose();
        _callAfterDisposal();
    }
}

Setting up the callback: 设置回调:

private unsafe NativeList<AStruct> GetAStructs()
{
    var floatList = new NativeList<float>();
    floatList.Add(0.0f);

    //here we construct the MyNativeList and pass it an action to execute when it is disposed
    var list = new MyNativeList<AStruct>( () => {
        callNativeFunction((AStruct*)floatList.Data);
        floatList.Dispose();
    });

    AStruct a1 = new AStruct();
    a1.floats = (float*)floatList.Data;
    list.Add(a1);

    // ...

    return list;
}

When you do this, the native list of floats is captured in a closed variable. 执行此操作时,浮点数的本机列表将捕获在一个封闭变量中。 Your caller just needs to dispose of the list per normal, and when the callback is made, the native list of floats gets disposed as well. 您的呼叫者只需要按常规处理该列表,并且在进行回调时,也会处理本机的float列表。

using ( var disposableList = GetAStructs() ) 
{
    //Do stuff
}

Notice that GetAStructs() still returns a reference to a NativeList<T> (not a MyNativeList<> ) so the implementation details do not leak to the caller unless they go out of their way to cast the result. 请注意, GetAStructs()仍返回对NativeList<T>的引用(不是MyNativeList<> ),因此实现细节不会泄漏给调用者,除非它们MyNativeList<>地投射结果。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM