C#中如何使一个集公共getter和setter方法​​和私有方法? [英] C# How to make public getters and setters and private methods for a collection?

查看:145
本文介绍了C#中如何使一个集公共getter和setter方法​​和私有方法?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想有一类A与(例如)排序列表集SrtdLst属性,而这个类中的A允许SrtdLst项加法或减法。但在A级的一个实例,只允许要获取或设置项目的内容,而不是增加新的项目或减去现有的。在代码:

I'd like to have a class "A" with a (for example) SortedList collection "SrtdLst" property, and inside this class "A" allow the addition or subtraction of "SrtdLst" items. But in a instance of the class "A", only allow to get or set the content of the items, not to add new items or subtract the existing ones. In code:

class A
{
    public SortedList<string, string> SrtdLst = new SortedList<string, string>();

    public A()
    {
        // This must work:
        SrtdLst.Add("KeyA", "ValueA");
        // This too:
        SrtdLst["KeyA"] = "ValueAAA";
    }
}

class B
{
    public A a = new A();
    public B()
    {
        // I want the following code to fail:
        a.SrtdLst.Add("KeyB", "ValueB");
        // But this must work:
        a.SrtdLst["KeyA"] = "ValueBBB";
   }
}



更​​新:我想创建一个类似系统的一类。 Data.SqlClient.SqlCommand。对于存储过程,你可以使用成员DeriveParameters填充参数的集合,所以只有每个项目可以修改的值。

UPDATE: I want to create a class like System.Data.SqlClient.SqlCommand. For the Stored Procedures you can use the member "DeriveParameters" that fills a collection of "Parameters", so only the value of each item can be modified.

哪有这怎么办?

推荐答案

如果你想在编译时禁止修改操作,你需要一个类型安全的解决方案。

If you want to ban the modifying operations at compile time, you need a type-safe solution.

声明一个接口,为公开允许的操作。 。使用该接口的属性类型

Declare an interface for the publicly allowed operations. Use that interface as the property type.

public interface IReadOnlyList<T>
{
    T this[int index] { get; }

    int Count { get; }
}



然后声明实现该接口和标准的集合类继承的类。

Then declare a class that implements that interface and inherits from the standard collection class.

public class SafeList<T> : List<T>, IReadOnlyList<T> { }



假设你有接口的定义吧,你将不再需要手工来实现什么,作为基类已经提供的实现。

Assuming you get the interface definition right, you won't need to implement anything by hand, as the base class already provides the implementations.

使用此派生类作为存储属性值的字段的类型。

Use that derived class as the type of the field that stores the property value.

public class A
{
    private SafeList<string> _list = new SafeList<string>();

    public IReadOnlyList<string>
    {
        get { return _list; }
    }
}



在A级,你可以使用 _list 直接,因此修改内容。 A类客户只能通过 IReadOnlyList<使用可用操作的子集; T>

Within class A, you can use _list directly, and so modify the contents. Clients of class A will only be able to use the subset of operations available via IReadOnlyList<T>.

有关你的榜样,你正在使用排序列表而不是List,所以接口可能需要将

For your example, you're using SortedList instead of List, so the interface probably needs to be

public interface IReadOnlyDictionary<K, V> : IEnumerable<KeyValuePair<K, V>>
{
    V this[K index] { get; }        
}



我将它继承了IEnumerable为好,这是只读,无论如何,所以是绝对安全的。然后,安全的类将是:

I've made it inherit IEnumerable as well, which is readonly anyway, so is perfectly safe. The safe class would then be:

public class SafeSortedList<K, V> : SortedList<K, V>, IReadOnlyDictionary<K, V> { }



但除此之外,它是相同的想法。

But otherwise it's the same idea.

更新:只注意到(出于某种原因我无法捉摸)你不想禁止修改操作 - 你只是想禁止一些修改操作。很奇怪,但它仍然是相同的解决方案。任何你想要的操作,以便在界面中的打开它们:

Update: just noticed that (for some reason I can't fathom) you don't want to ban modifying operations - you just want to ban SOME modifying operations. Very strange, but it's still the same solution. Whatever operations you want to allow, "open them up" in the interface:

public interface IReadOnlyDictionary<K, V> : IEnumerable<KeyValuePair<K, V>>
{
    V this[K index] { get; set; }        
}



当然,这是接口的错名字了......为什么在地球上,你会要禁止通过添加加,而是通过索引不禁止呢? (索引器可以用来添加项目,就如同添加方法。)

Of course, that's the wrong name for the interface now... why on earth would you want to ban adding via Add but not ban it via the indexer? (The indexer can be used to add items, just as the Add method can.)

更新

从你的评论,我认为你的意思是要允许分配到现有的键/值对的值,但不允许分配给一个先前未知的关键。显然,作为密钥由字符串在运行时指定的,有没有办法赶上,在编译时。所以,你不妨去运行时检查:

From your comment I think you mean that you want to allow assignment to the value of an existing key/value pair, but disallow assignment to a previously unknown key. Obviously as keys are specified at runtime by strings, there's no way to catch that at compile time. So you may as well go for runtime checking:

public class FixedSizeDictionaryWrapper<TKey, TValue> : IDictionary<TKey, TValue>
{
    IDictionary<TKey, TValue> _realDictionary;

    public FixedSizeDictionaryWrapper(IDictionary<TKey, TValue> realDictionary)
    {
        _realDictionary = realDictionary;
    }

    public TValue this[TKey key]
    {
        get { return _realDictionary[key]; }

        set 
        {
            if (!_realDictionary.Contains(key))
                throw new InvalidOperationException();

            _realDictionary[key] = value;
        }
    }

    // Implement Add so it always throws InvalidOperationException

    // implement all other dictionary methods to forward onto _realDictionary
}

你有一个普​​通的字典,你希望把它交给一些你不'方法的任何时间ŧ信任更新现有的价值,把它包在其中的一个。

Any time you have an ordinary dictionary and you want to hand it to some method that you don't trust to update the existing values, wrap it in one of these.

这篇关于C#中如何使一个集公共getter和setter方法​​和私有方法?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆