如何声明get和设置类的List属性的访问器

时间:2015-01-10 17:41:39

标签: c# collections getter

我有一个拥有属性

的Teacher类
class Teacher:Employee
    {
        //private List<string> SubjectTaughtList = new List<string>();

        public string SubjectTaught { get; set; }

        public string Qualification{ get; set; }

        public Teacher() { }

        public Teacher(string id,string title, string fn,string ln, DateTime dob, 
                       string gender,string houseno,string street,string city,string county,
                       string phone,string workPhone, string email,string workEmail,DateTime doj,
                       string status,decimal sal,List<string> subject,string qualification)
            : base(id, title, fn,ln, dob, gender,houseno,street,city,county, phone, 
                   workPhone, email, workEmail, doj, status, sal)
        {
            SubjectTaught = subject;
            Qualification = qualification;
        }
    }

我想为SubjectTaught创建一个列表,因为它将有多个值。我在Windows窗体中创建了一个checkedListbox,但我不知道如何获取和设置属性。

我认为它应该是只读的,因为我已经拥有了例如Art,Law等列表的值,或者可能是我错了,因为我将根据选中的列表框创建列表。

我是C#的新手,所以我处于初级水平,所以非常困惑它是如何工作的。请指教

1 个答案:

答案 0 :(得分:3)

对于.NET 3.5

即使您具有List类型的只读属性,也可以从对象外部进行修改,因为它是引用类型。如果您不需要索引器和Count,可以更好地encapsulation使用IEnumerable。这样的对象不能从类的外部修改,除了项目,这些都可以修改,即使它是IEnumerable。 IEnumerable可以通过强制转换回List而被修改。

public IEnumerable<string> SubjectTaught  { get; }

或者您可以使用ReadOnlyCollection。这将为您提供Count属性+索引器,它不包含在IEnumerable中。 ReadOnlyCollection的所有更改都适用于包装器而不是原始集合,这意味着封装甚至可以实现。

private List<string> _subjectTaught;

public ReadOnlyCollection<string> SubjectTaught
{ 
   get{ _subjectTaught.AsReadOnly();}
}

对于.NET 4.5

在.NET Framework 4.5中,您可以使用由List和IReadOnlyCollection实现的ReadOnlyCollection。使用AsReadOnly + IReadOnlyCollection会阻止调用者在将IReadOnlyCollection强制转换回List后修改IReadOnlyCollection,因为所有更改都是对AsReadOnly包装器进行的,而不是对集合本身进行的更改。

private List<string> _subjectTaught;

public IReadOnlyCollection<string> SubjectTaught
{ 
   get{ _subjectTaught.AsReadOnly();}
}

仅返回IReadOnlyCollection作为List的接口不提供只读包装器,从而通过将属性转换回List并修改原始集合来启用hack:

private List<string> _subjectTaught;

public IReadOnlyCollection<string> SubjectTaught
{ 
   get{ _subjectTaught;}
}

请参阅comparing IReadOnlyCollection and ReadOnlyCollection

为了更好地理解,请尝试以下示例:

public class MyClass
{
    private List<string> _list = new List<string>();

    public MyClass()
    {
        _list.Add("banana");
        _list.Add("orange");
        _list.Add("apple");
    }

    public IReadOnlyCollection<string> ReadOnly
    {
        get { return _list; }
    }

    public IReadOnlyCollection<string> ReadOnlyWithWrapper
    {
        get { return _list.AsReadOnly(); }
    }
}

class Program
{
    static void Main(string[] args)
    {
        MyClass my = new MyClass();

        //modify by hack
        ((List<string>)my.ReadOnly).Add("Cherries");

        Console.WriteLine("no wrapper");

        foreach (var item in my.ReadOnly)
        {
            Console.WriteLine(item); //will include cherries
        }

        Console.WriteLine("with wrapper");


        MyClass my2 = new MyClass();

        //cannot be modify by hack, unless reflection is used
        //throw InvalidCastException
        ((List<string>)my2.ReadOnlyWithWrapper).Add("cherries");    
    }
}

注意: 感谢Scott Chamberlain关于.NET 4.5中的IReadOnlyCollection的评论