1

我一直在环顾四周,到目前为止还没有找到一个好的方法来做到这一点。这是一个普遍的问题,我敢肯定。

假设我有以下内容:

class SomeClass : IComparable
{ 
    private int myVal; 
    public int MyVal
    { 
        get { return myVal; } 
        set { myVal = value; }
    }

    public int CompareTo(object other) { /* implementation here */ }
}

class SortedCollection<T>
{
    private T[] data;
    public T Top { get { return data[0]; } }

    /* rest of implementation here */
}

想法是,我要实现一个二进制堆,而不是只支持 Insert() 和 DeleteMin() 操作,我想支持“偷看”最高(或最低,视情况而定)优先级值在堆栈上。从来没有像海森堡那样,整个“你不能在不改变它们的情况下看待事物”不确定性原则。垃圾!

显然,问题在于上述方法无法阻止调用代码通过 Top 属性修改 MyVal(假设为 SortedCollection),该操作很可能会将我的堆置于错误的顺序。有什么方法可以防止修改通过 Top 属性应用于堆的内部元素?还是我只是使用带有警告的代码:“只有在插入和出列之间不修改任何实例时才稳定。YMMV。”

4

5 回答 5

1

您可以拥有一个只读属性(即只有一个 getter 的属性):

private int myVal;
public int MyVal { get { return myVal; } }

但要小心:这可能并不总是如您所愿。考虑:

private List<int> myVals;
public List<int> MyVals { get { return myVals; } }

在这种情况下,您无法更改该类使用的 List,但您仍然可以调用该 List 的.Add().Remove()等方法。

于 2009-07-20T23:14:05.110 回答
1

您的属性不必具有与get/相同的可访问性set。这涵盖了任何返回值类型(通常structs 只包含值类型)或不可变引用类型的东西。

public int MyVal
{ 
    get { return myVal; } 
    private set { myVal = value; }
}

对于可变引用类型,您还有其他选项,例如返回Clone()s 或使用ReadOnlyCollection<T>来阻止调用者更改它们:

private List<int> data;

public IList<int> Data
{
    get { return new ReadOnlyCollection<int>(this.data); }
}
于 2009-07-20T23:18:06.770 回答
1

回答你的问题:,没有办法实现你想要的那种行为——只要 T 是引用类型(甚至可能是一些值类型)

你真的无能为力。只要您提供一个getter,调用代码就可以根据所述数据的可访问性(即属性、字段和方法)修改数据的内部内容。

class SomeClass : IComparable
{ 
    private int myVal; 
    public int MyVal
    { 
        get { return myVal; } 
        set { myVal = value; }
    }

    public int CompareTo(object other) { /* implementation here */ }
}


class SortedCollection<T>
{
    private T[] data;
    public T Top { get { return data[0]; } }

    /* rest of implementation here */
}

//..
// calling code
SortedCollection<SomeClass> col;
col.Top.MyVal = 500;  // you can't really prevent this

注意我的意思是,在你无法控制的类的情况下,你不能真正阻止它。在示例中,就像其他人所说的那样,您可以将 MyVal 的设置设为私有或省略它;但是由于 SortedColleciton 是一个泛型类,你不能对其他人的结构做任何事情..

于 2009-07-20T23:29:03.707 回答
0

仅为您的属性实现 getter 并通过添加/删除方法修改集合

于 2009-07-20T23:17:04.217 回答
0

我现在明白你的问题了。我认为这应该有效:

class SortedCollection<T> where T: ICloneable
{
    private T[] data;
    public T Top 
    { 
         get 
         { 
             T ret = (T)data[0].Clone();
             return ret; 
         }
    }

    /* rest of implementation here */
}

ICloneable 约束确保类型参数实现 ICloneable 接口。(如果这是可以接受的)

于 2009-07-21T01:38:37.863 回答