0

我有一个像这样拥有 Texture2D 的类:

public class TextureData
{
    public Texture2D texture;
}

当我加载所有纹理时,我通过以下方法处理它:

public void LoadAllTextures()
{
    foreach(string s in texturesToBeLoaded)
    {
        TextureData data = new TextureData();
        LoadTexture(s, data.texture);
        // data.texture is still null.
    }
}
public void LoadTexture(string filename, Texture2D texture)
{
    texture = content.Load<Texture2D>(filename);
    // texture now holds the texture information but it doesn't
    // actually retain it when the method ends...why?
}

我在这里错过了什么吗?如果我改变

public void LoadTexture(string filename, Texture2D texture)

public void LoadTexture(string filename, out Texture2D texture)

它工作正常。


编辑:好吧,我现在理解的方式是这样的......

public void LoadAllTextures()
{
    foreach(string s in texturesToBeLoaded)
    {
        TextureData data = new TextureData();
        // here, data.texture's memory address == 0x0001
        LoadTexture(s, data.texture /*0x0001*/);
    }
}
public void LoadTexture(string filename, Texture2D texture /* this is now 0x0001 */)
{
    texture = content.Load<Texture2D>(filename);
    // now the PARAMETER is set to 0x0002, not data.texture itself.
}
4

4 回答 4

3

C# 按值传递变量 - 传递了引用的副本,但原始变量或字段保持不变。添加out(或ref)使其通过引用传递,然后导致原始变量/字段被更新。

于 2012-08-15T10:11:16.363 回答
1

卢塞罗的回答是正确的——你要做的实际改变是改变你的工作方法,如下所示:

public void LoadAllTextures()
{
    foreach(string s in texturesToBeLoaded)
    {
        TextureData data = LoadTexture(s);
        // do something with data here
    }
}

public Texture2D LoadTexture(string filename)
{
    Texture2D texture = content.Load<Texture2D>(filename);
    return texture;
}
于 2012-08-15T10:15:00.810 回答
1

那是因为您正在修改引用的副本。假设前面data.texture指向一个内存位置048,当您调用LoadTexture(s, data.texture);参数时,纹理现在保存该值048。在您方法的第一行中,您LoadTexture为其分配了一个新的内存位置,因此现在texture指向全新的东西,但不是048. 这就是为什么你看不到任何变化。

但是,如果您更新 的任何属性texture,您也会看到原始数据的变化。

考虑以下情况:

public class TempClass
{
    public string MyProperty { get; set; }
}

在您的Main方法中,您可以执行以下操作:

TempClass tc = new TempClass();
tc.MyProperty = "Some value";
SomeMethod(tc);

您的 SomeMethod 在哪里:

public static void SomeMethod(TempClass temp)
{
    temp = null;
}

现在这不会将对象设置tcTempClass空。

您应该看到 Jon Skeet 的这篇文章:C# 中的参数传递

于 2012-08-15T10:15:54.153 回答
1

混淆可能来自通过引用传递的含义。在 C# 中,对象是通过引用传递的。这意味着如果您在函数中修改对象的属性,这些更改将反映在调用函数中,并且它们都具有对同一对象的引用。但是,按引用传递并不意味着如果您在函数中更新变量以引用不同的对象(例如,通过创建新对象),调用函数中的变量将被更新为引用相同的对象。如果这是您想要的行为,您必须使用 ref 或 out。

于 2012-08-15T10:17:24.277 回答