c# - 如何声明类的 List 属性的获取和设置访问器

标签 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,但我不知道如何获取和设置该属性。

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

我是 C# 的新手,所以我处于初学者水平,所以对它的工作方式非常困惑。请指教

最佳答案

对于 .NET 3.5

即使你有 List 类型的只读属性,它也可以从对象外部修改,因为它是引用类型。为了更好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 中,您可以使用 IReadOnlyCollection由 List 和 ReadOnlyCollection 实现以及。使用 AsReadOnly + IReadOnlyCollection 可防止调用者在将 IReadOnlyCollection 转换回 List 后修改 IReadOnlyCollection,因为所有更改都是针对 AsReadOnly 包装器而不是集合本身进行的。

private List<string> _subjectTaught;

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

仅返回 IReadOnlyCollection 作为 List 的接口(interface)不提供只读包装器,因此通过将属性强制转换回 List 并修改原始集合来实现黑客攻击:

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 的评论

关于c# - 如何声明类的 List 属性的获取和设置访问器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27879169/

相关文章:

javascript - 使用 Promise 处理 firestore 任务

java - 在 Java/Android 中,我是通过 Intent 还是使用 getter/setter 传递值?

C# EF6 条件属性选择?

c# - 尝试从 Web 应用程序打印时出现错误 "The RPC server is unavailable"

java - 如何使用java从列表中删除重复项和匹配的原始元素

php - 在 PHP 中使用 getter 和 setter 代替函数或简单的公共(public)字段有什么好处?

python - 为什么使用 lambda 函数将其设为属性?

c# - 我可以通过编程方式更改我发送的电子邮件中的字体和字体大小吗?

c# - 如果我尝试选择一些数据 : 'windows-1252' is not a supported encoding name,我会收到此错误

java - 为数组实现撤销和重做