简体   繁体   English

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

[英]How to declare get and set accessors of a List property of a class

I have a Teacher class which has a property 我有一个教师班,有一个属性

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

I want to create a list for SubjectTaught as it will have more than one value. 我想为SubjectTaught创建一个列表,因为它将有多个值。 I am creating a checkedListbox in windows form but I don't know how to get and set the property. 我在Windows窗体中创建一个checkedListbox但我不知道如何获取和设置属性。

I think it should be read-only as I already have the values for the list for eg Art,Law,etc or may be I am wrong as I the list will be created as per the checked listbox. 我认为它应该是只读的,因为我已经有了例如Art,Law等列表的值,或者可能是我错了,因为我将按照选中的列表框创建列表。

I am new to C# so I am at beginner level so very confused as to how it will work. 我是C#的新手,所以我处于初级水平,所以我很困惑它是如何工作的。 Please advise 请指教

For .NET 3.5 对于.NET 3.5

Even if you have readonly property of type List, it can be modified from outside of the object, because it is reference type. 即使您具有List类型的只读属性,也可以从对象外部进行修改,因为它是引用类型。 For better encapsulation use IEnumerable if you don't need indexer and Count. 为了更好的封装,如果您不需要索引器和Count,请使用IEnumerable Such object cannot be modified from the outside of the class, except items, these can be modified even it is IEnumerable. 这样的对象不能从类的外部修改,除了项目,这些都可以修改,即使它是IEnumerable。 IEnumerable can be hacked by casting back to the List and then modified. IEnumerable可以通过强制转换回List然后修改来攻击。

public IEnumerable<string> SubjectTaught  { get; }

Or you can use ReadOnlyCollection . 或者您可以使用ReadOnlyCollection This will provide you Count property + indexer, which is not included in IEnumerable. 这将为您提供Count属性+索引器,它不包含在IEnumerable中。 All changes of ReadOnlyCollection apply to the wrapper not to the original collection, it means the encapsulation goes even far. ReadOnlyCollection的所有更改都适用于包装器而不是原始集合,这意味着封装甚至可以实现。

private List<string> _subjectTaught;

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

For .NET 4.5 对于.NET 4.5

In NET Framework 4.5 you can use IReadOnlyCollection which is implemented by List and by ReadOnlyCollection as well. 在.NET Framework 4.5中,您可以使用由List和ReadOnlyCollection实现的IReadOnlyCollection Usage of AsReadOnly + IReadOnlyCollection prevent caller from modifying the IReadOnlyCollection after casting IReadOnlyCollection back to List, because all changes are made to AsReadOnly wrapper, not the collection itself. 使用AsReadOnly + IReadOnlyCollection会阻止调用者在将IReadOnlyCollection强制转换回List之后修改IReadOnlyCollection,因为所有更改都是对AsReadOnly包装器进行的,而不是对集合本身进行的。

private List<string> _subjectTaught;

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

Returning only IReadOnlyCollection as interface of List doesn't provide the readonly wrapper and thus enable a hack by casting the property back to List and modifying the original collection: 仅返回IReadOnlyCollection作为List的接口不提供只读包装器,从而通过将属性转换回List并修改原始集合来启用hack:

private List<string> _subjectTaught;

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

See comparing IReadOnlyCollection and ReadOnlyCollection . 请参阅比较IReadOnlyCollection和ReadOnlyCollection

For better understanding try this example: 为了更好地理解,请尝试此示例

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

NOTES: Thanks to Scott Chamberlain's comment about IReadOnlyCollection in .NET 4.5 注意:感谢Scott Chamberlain关于.NET 4.5中的IReadOnlyCollection的评论

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM