0

*解决了。感谢各位的解释,我没有完全理解在这种情况下使用值类型的含义。

我有一个从静态类中使用的结构。但是,当我在运行时打印其内部状态时,该行为显示出意外行为。这是我的结构:

    public struct VersionedObject
    {

        public VersionedObject(object o)
        {
            m_SelectedVer = 0;
            ObjectVersions = new List<object>();
            ObjectVersions.Add(o);
        }

        private int m_SelectedVer;
        public int SelectedVersion
        {
            get
            {
                return m_SelectedVer;
            }

        }

        public List<object> ObjectVersions;//Clarifying:  This is only used to retrieve values,  nothing is .Added from outside this struct in my code.

        public void AddObject(object m)
        {
            ObjectVersions.Add(m);
            m_SelectedVer = ObjectVersions.Count - 1;
        }
    }

测试代码

        VersionedObject vo = new VersionedObject(1);
        vo.AddObject(2);//This is the second call to AddObject()
        //Expected value of vo.SelectedVerion:  1
        //Actual value of vo.SelectedVersion:   1

现在,如果您单独测试此代码,即,将其复制到您的项目中试一试,它将返回预期的结果。

问题; 我在生产代码中观察到的是这个调试输出:

objectName, ObjectVersions.Count:2, SelectedVer:0,

为什么?根据我的理解和测试,这在任何情况下都应该是完全不可能的。

我的随机猜测是存在某种不变性,由于某种原因,正在通过默认构造函数实例化一个新结构,并且正在复制 ObjectVersions 数据,但是 m_SelectedVersion 是私有的,不能复制到新结构中?
我使用静态类和方法来操作结构与它有什么关系吗?

我很困惑,我现在只是在胡乱猜测。

4

2 回答 2

1

结构是值类型。因此,您很可能正在实际代码中创建对象的多个副本。

考虑简单地将结构更改为类,因为结构的内容并不适合值类型(因为它是可变的并且还包含可变引用类型)。

有关“结构是值类型”的更多信息:

首先检查已经有很多好的答案的常见问题解答。

值类型是按值传递的 - 因此,如果您调用函数来更新此类对象,它将不会更新原始对象。您可以将它们类似于将整数值传递给函数:即您希望SomeFunction(42)能够更改 42 的值吗?

struct MyStruct { public int V;}
void UpdateStruct(MyStruct x)
{
  x.V = 42; // updates copy of passed in object, changes will not be visible outside.
}
....
var local = new MyStruct{V = 13}
UpdateStruct(local); // Hope to get local.V == 42
if (local.V == 13) {
  // Expected. copy inside UpdateStruct updated,
  // but this "local" is untouched.
}
于 2012-08-07T00:21:55.993 回答
1

为什么这是一个结构而不是一个类?更好的是,您为什么要跟踪后备存储 ( List<T>) 的大小,而不是让List<T>跟踪为您服务。由于该底层后备存储是公共的,因此可以在您的结构不知情的情况下对其进行操作。我怀疑您的生产代码中的某些内容正在添加到后备存储中而无需通过您的结构。

如果是我,我会设置这样的东西,虽然我会把它变成一个类......但这几乎可以肯定是一个突破性的变化:

public struct VersionedObject
{

    public VersionedObject()
    {
        this.ObjectVersions = new List<object>() ;
        return ;
    }

    public VersionedObject(object o) : this()
    {
        ObjectVersions.Add(o);
        return ;
    }
    public VersionedObject( params object[] o ) : this()
    {
        ObjectVersions.AddRange( o ) ;
        return ;
    }

    public int SelectedVersion
    {
        get
        {
            int value = this.ObjectVersions.Count - 1 ;
            return value ;
        }
    }
    public List<object> ObjectVersions  ;

    public void AddObject(object m)
    {
        ObjectVersions.Add(m);
        return ;
    }

}

您会注意到这与您的结构具有相同的语义,但该SelectedVersion属性现在反映了后备存储中的实际内容。

于 2012-08-07T00:39:16.607 回答