【问题标题】:fixed block in .net.net 中的固定块
【发布时间】:2012-04-19 11:59:55
【问题描述】:

我对何时需要固定块感到有些困惑。我有一个例子,它给了我一个矛盾的场景:

enum RoomType { Economy, Buisness, Executive, Deluxe };

struct HotelRoom
{
    public int Number;
    public bool Taken;
    public RoomType Category;

    public void Print()
    {
        String status = Taken ? "Occupied" : "available";
        Console.WriteLine("Room {0} is of {1} class and is currently {2}", Number, Category, status);
    }
}

我已经创建了一个函数,它将指向 HotelRoom 的指针

private unsafe static void Reserve(HotelRoom* room)
{
    if (room->Taken)
        Console.WriteLine("Cannot reserve room {0}", room->Number);
    else
        room->Taken = true;
}

在主要方法中,我有以下内容:

unsafe static void Main(string[] args)
{
    HotelRoom[] myfloor = new HotelRoom[4];
    for (int i = 0; i < myfloor.Length; i++)
    {
        myfloor[i].Number = 501 + i;
        myfloor[i].Taken = false;
        myfloor[i].Category = (RoomType)i;
    }
    HotelRoom Room =  myfloor[1];
    Reserve(&Room);   //I am able to do this without fixed block.
    //Reserve(&myfloor[1]);  //Not able to do this so have to use fixed block below. 

    fixed (HotelRoom* pRoom = &myfloor[1])
    {
        Reserve(pRoom);
    }

    myfloor[1].Print();
    Room.Print();
}

我的困惑是我能够做到Reserve(&amp;Room),但不能做到Reserve(&amp;myfloor[1])。我认为他们在做同样的事情——将HotelRoom 结构的内存地址传递给Reserve 函数。为什么我需要fixed 来执行此操作?

【问题讨论】:

    标签: .net pointers garbage-collection fixed unsafe


    【解决方案1】:

    Room 是存储在栈中的局部变量,而myfloor 存储在堆中。垃圾收集器可以移动堆中的对象来压缩它(地址会改变),所以你需要“固定”它们。这就是您需要fixed 声明的原因。

    更新:

    此外,还有一种方法可以在堆中的堆栈上分配内存:

    HotelRoom* fib = stackalloc HotelRoom[4];

    在这种情况下,您不需要fixed 声明。

    小声明:能够做到这一点并不意味着你当然应该这样做。正如其他人已经提到的那样,这是一种非常非 .NET 的代码编写方式,所以我只是认为这个问题是理论上的。

    【讨论】:

    • 让我完全错过了这一点.. 你立即指出。谢谢。
    【解决方案2】:

    这只是一个扔掉的例子吗?

    或者...

    我猜你正在尝试将 C++ 重写为 C#。您很少需要使用unsafe,.NET 的主要特点是它是一个托管框架。

    除非我在这里完全错了(您的所有代码都可以编写为托管代码),否则您应该阅读非托管代码和托管代码之间的区别,尤其是如何编写来自 C++ 背景的 C#。

    看看这些:

    what is the difference between “managed” vs “unmanaged”?

    Difference between Managed Code and Unmanaged Code?

    C# for C++ Developers

    .NET Book Zero

    (编辑自C# books or web sites for C++ developers [closed]

    【讨论】:

    • 你猜我也有 C++ bagrounds。我想知道我可以通过 uisng ref 关键字来传递参数来做到这一点。在 C# 中,有时我们需要指针,我注意到的一个实例是。假设我想要实现字符串反转,那么只有我们能想到的是。
    • 使用系统;类测试{私有不安全静态无效反向(字符串文本){固定(char * pStr = text){char * pBegin = pStr; char* pEnd = pStr + text.Length - 1;而(pBegin
    • link 给出了关于托管/非托管代码的好主意。我想知道是否不推荐使用未管理的代码,为什么微软将其保留在 .Net 框架中??
    • unsafe 之所以存在,是因为它对性能很有用(例如,使用指针沿长“字符串”迭代使用指针,而不用担心溢出检查,例如 CRC 实现可以利用这一点),尤其是对于 InterOp(从 .NET 访问 COM 对象)通常必要。对于字符串反转,您只需向后遍历字符串,随时创建一个新的“StringBuilder”,不需要指针:)
    • 哦,在所有 .NET 代码下面,当然,实际工作将在指针中完成。但是,托管框架隐藏了所有这些复杂性和潜在的错误。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-08-04
    • 1970-01-01
    • 1970-01-01
    • 2022-01-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多