我在C ++和Qt延长一段时间后才回到C#。我目前被我认为是一个非常简单的问题所困扰。
我有一个结构:
struct FontGlyph {
public uint codepoint;
public byte[] bmp;
...
}
还有一系列结构:
FontGlyph[] glyphs = new FontGlyph[100];
现在,我有几个函数可以设置和修改结构中的字段:
static void ConvertFont(Font fnt) {
...
if (fnt.IsSpaceCharacter) {
glyphs[idx].codepoint = 0x00FF;
glyphs[idx].bmp = null;
}
else {
RenderFontGlyph(glyphs[idx]);
// glyphs[idx].bmp is NOT ok here - it is null!
}
...
}
static void RenderFontGlyph(FontGlyph glyph) {
...
glyph.bmp = new byte[256];
// bmp is fine here, and can be populated as a normal array
...
}
这不是特别好的代码片段,但是,在RenderFontGlyph函数中,我可以看到bmp
数组在RenderFontGlyph函数返回时正确分配,检查{{1 }}变量,glyphs[idx]
返回null。
我很欣赏我可能会做一些事情,但已经有一段时间了。我是垃圾收集的受害者还是我是傻瓜?在我看来,结构被传递到bmp
函数by-value而不是by-ref,但这也没有区别!
答案 0 :(得分:4)
我发现结构是通过-val而不是-ref传递给RenderFontGlyph函数的,但这也没有区别!
是的,确实如此。您正在创建结构的副本,并将其传递到RenderFontGlyph
。对该副本所做的任何更改都不会影响其他任何内容。
如果您通过引用传递它,将有所作为,因为您将修改数组中的原始存储位置:
RenderFontGlyph(ref glyphs[idx]);
...
static void RenderFontGlyph(ref FontGlyph glyph)
或者您可以继续使用值参数,并根据Leonardo的回答,让RenderFontGlyph
返回您需要存储在数组中的修改后的值。
我当然不会说你是愚蠢的,但是你了解{{3}真的非常重要如果您正在创建可变值类型,则特别。 (更糟糕的是,一个包含对可变引用类型的引用的可变值类型 - 在这种情况下是数组。您可以在不改变结构的情况下改变数组...如果您不小心,这可能会变得非常混乱。 )
除非您有充分的理由创建可变价值类型,否则我强烈反对它 - 就像我也建议不要暴露公共领域。你几乎肯定会将FontGlyph
建模为一个类 - 它对我来说并不像一个自然的价值类型。如果做想要将其建模为值类型,那么为什么不在中传递所需的代码点,而不是传入FontGlyph
。渲染,并使方法返回字形?
glyphs[0] = RenderGlyph(codePoint);
由于您声称传递引用并不适合您,这里有一个完整的示例,证明它 正常工作。你应该将它与你的代码进行比较,看看你做错了什么:
using System;
struct FontGlyph
{
public uint codepoint;
public byte[] bmp;
}
class Program
{
static void Main()
{
FontGlyph[] glyphs = new FontGlyph[100];
RenderFontGlyph(ref glyphs[0]);
Console.WriteLine(glyphs[0].bmp.Length); // 10
}
static void RenderFontGlyph(ref FontGlyph glyph)
{
glyph.bmp = new byte[10];
}
}
答案 1 :(得分:1)
怎么样:
static void ConvertFont(Font fnt) {
...
if (fnt.IsSpaceCharacter) {
glyphs[idx].codepoint = 0x00FF;
glyphs[idx].bmp = null;
}
else {
glyphs[idx] = RenderFontGlyph(glyphs[idx]);
// glyphs[idx].bmp is NOT ok here - it is null!
}
...
}
static FontGlyph RenderFontGlyph(FontGlyph glyph) {
...
glyph.bmp = new byte[256];
// bmp is fine here, and can be populated as a normal array
...
return glyph;
}
或使用ref
,如下所示:static void RenderFontGlyph(ref FontGlyph glyph)
,然后按照以下方式调用它:RenderFontGlyph(ref glyphs[idx])