c#结构参考以防止复制

c#结构参考以防止复制,c#,struct,copy,ref,C#,Struct,Copy,Ref,我需要在类中有一个私有结构成员,并且正在寻找一种方法来访问该结构成员,而不执行复制 原因是该结构被用作c dll的接口 public class MyCDllApi { // Marshalled struct [StructLayout(LayoutKind.Sequential)] public struct DllData { [MarshalAs(UnmanagedType.U1)] public byte data1; [

我需要在类中有一个私有结构成员,并且正在寻找一种方法来访问该结构成员,而不执行复制

原因是该结构被用作c dll的接口

public class MyCDllApi
{
    // Marshalled struct
    [StructLayout(LayoutKind.Sequential)]
    public struct DllData
    {
        [MarshalAs(UnmanagedType.U1)] public byte data1;
        [MarshalAs(UnmanagedType.U1)] public byte data2;
        // ...
        // lots more; this is really a LARGE struct
    }

    // DLL Function call
    [DllImport("MyC.dll",  CallingConvention=CallingConvention.Cdecl)]
    private static extern int do_some_work(ref DllData data);

    public void doSomeWork()
    {
        do_some_work(ref m_dllData);
    }
    public DllData getData();

    private DllData m_dllData;
}

public class MyProg
{
    static void Main(String args[])
    {
        MyC_DllApi m_dllApi = new MyCDllApi();
        m_dllApi.doSomeWork();
        DllData data = m_dllApi.getData();

        // Use data
    }
}
我想我可以将结构装箱并从getData()返回一个对象,但是这意味着需要强制转换

我还认为我可以在类中包含结构,并且可以将其作为引用传递,但是提供的任何检索结构成员的方法都将执行复制

另一个想法是公开数据

可以有人告诉我C++中这种情况下的正常解决方案,即C++中返回“const &”的等价性。出于性能原因,我是否希望避免创建结构副本?我可以通过ref将结构作为函数参数传递。我不能返回类成员结构的引用吗

编辑

只是澄清一下,在本例中,我使用的是struct,因为它符合DLL的API,我认为与此API保持一致是很好的。我不是在要求用一个类来代替这个。同样地,我也不想寻找一个使类更复杂的解决方案。

我希望MyCDllApi是c dll的一个简单的非智能c#包装器。我想问的是,是否有任何合理的方法可以避免每次外部对象访问该类以检索DllData时都使用struct copy。也就是说,类似于C++中的“const &”。< /强>

如果这样的解决方案/模式在C#中不常用或不合适,那么这很好。我的程序可以处理结构副本的开销。我只是想问这个问题。


谢谢你的评论,听起来你有三个选择:

  • [SequentialLayout]
    一起使用;参见示例

  • 不要试图在
    getData()
    中返回整个结构,而只返回调用方真正感兴趣的部分。在此基础上的一个变体是传入一个
    Func
    (或
    Action
    )对结构进行操作。这两种技术都避免了复制

  • C++中C++的工作原理;在C++/CLI中实现
    doSomeWork()
    ,而不是在C#中实现。这也避免了从C#中的.h文件复制(大)结构


    这个结构太小了,你为什么担心它会被复制呢?你可能想重新命名你的问题,以便更能描述这个问题。另外,作为旁注,C#标准是
    MethodName()
    而不是
    MethodName()
    ,匈牙利符号有点不相等。所示的结构就是一个例子。为了简单起见,我把它缩小了。真正的结构是相当大的。它已经这样工作了,结构是可轻击的。因此pinvoke封送器将传递一个指向存储在类对象中的结构的指针,本机代码将直接涂鸦到GC堆中。您正在尝试优化不需要任何帮助的内容。只有在知道性能问题时才优化代码。您可以将
    顺序布局
    一起使用。这已经是一个“指针”,所以将其定义为
    做一些工作(DllData数据)
    。谢谢。我没有更改dll的范围,因此无法执行选项1。我的类的目标是简单地实现c#/c接口,即为c dll提供一个包装器,并让外部类做更多有意义的工作。我不想给类的用户提供限制,也不想在MyCDllApi中执行任何功能,除了作为dll的哑包装器。@user1400716:通过p/invoke封送将涉及复制数据,句号。NET不会让你的C++在你的脚上射击你的C。而且,您可以将数据封送为
    ,就像封送
    结构一样容易;p/Unjk不关心(对于非托管代码也没有C++),<代码>类< /COD>和结构> < />代码完全有相同的实现。嗯,丹的#3建议很可能会让你接近你想要的目标,但问题中没有足够的细节可以确定。@PeterDuniho:可以通过引用来封送blittable类型;在.NET端,它们作为
    ref
    参数传递,而在本机端,它们被声明为指针。当.NET通过引用传递包含在对象字段中的结构时,该对象将被固定,直到该方法返回为止。@supercat:谢谢,你说得对。在这种情况下,.NET确实让你的C++在你的脚上射击你的C。因此,基本上:OP的代码已经完成了他要求它做的事情,只要他坚持使用
    struct