2

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

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(&Room)但不能Reserve(&myfloor[1])。我认为他们在做同样的事情——将HotelRoom结构的内存地址传递给Reserve函数。为什么我需fixed要这样做?

4

2 回答 2

1

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

更新:

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

HotelRoom* fib = stackalloc HotelRoom[4];

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

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

于 2012-04-19T12:05:20.080 回答
1

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

或者...

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

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

看看这些:

“托管”与“非托管”有什么区别?

托管代码和非托管代码之间的区别?

面向 C++ 开发人员的 C#

.NET 零书

(编辑自C# 书籍或 C++ 开发人员网站 [关闭]

于 2012-04-19T12:07:15.493 回答