为什么不通过没有'out'的方法分配Texture2D?

时间:2012-08-15 10:09:26

标签: c# xna

我有一个类似于持有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 个答案:

答案 0 :(得分:3)

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

答案 1 :(得分:1)

Lucero的回答是正确的 - 你要做的实际改变是改变你的方法如下工作:

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;
}

答案 2 :(得分: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;
}

现在不会将tc的对象TempClass设置为null。

你应该看到Jon Skeet的这篇文章:Parameter passing in C#

答案 3 :(得分:1)

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