当需要固定块时,我有点困惑。我有一个例子,它给了我一个矛盾的场景:
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
来执行此操作?
答案 0 :(得分:1)
Room
是一个局部变量,存储在堆栈中,而myfloor
存储在堆中。垃圾收集器可以移动堆中的对象来压缩它(地址会改变),所以你需要“固定”它们。这就是你需要fixed
陈述的原因。
<强>更新强>
此外,还有一种方法可以在堆栈堆栈上分配内存:
HotelRoom* fib = stackalloc HotelRoom[4];
在这种情况下,您不需要fixed
声明。
小号免责声明能够做到这一点并不意味着你当然应该这样做。正如其他人已经提到的,这是非常非编写代码的方式,所以我只想把这个问题理论化。
答案 1 :(得分:1)
这只是一个抛弃的例子吗?
...或
我猜你正在尝试将C ++重写为C#。您很少需要使用unsafe
,.NET的主要观点是它是一个托管框架。
除非我在这里完全错误(您的所有代码都可以编写为托管代码),否则您应该了解非托管代码和托管代码之间的差异,尤其是如何编写来自C ++背景的C#。
看看这些:
what is the difference between “managed” vs “unmanaged”?