数组结构中的C#数组丢失内容

时间:2017-05-19 19:05:05

标签: c# arrays struct null

我在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,但这也没有区别!

2 个答案:

答案 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])