我不太清楚我是否理解OOP原则阻止我使用类型B中的方法来构建类型A。
具体示例:
using System;
using System.Collections.Generic;
using System.Linq;
public class Program
{
public static void Main()
{
string[] week = new string[] { "Monday", "Tuesday", "wednesday", "Saturday", "Sunday"};
ICollection<string> coll = (ICollection<string>)week;
coll.Add("SlaveDay"); // this throws an error
ICollection<string> coll2 = new List<string>() { "Monday", "Tuesday", "wednesday", "Saturday", "Sunday" };
coll2.Add("SlaveDay"); // this works
}
}
当然,数组是固定大小的,所以我理解为什么周(类型为string[]
或字符串数组)不能添加任何新元素。
但是,在我明确地将它转换为ICollection<string>
(顺便说一下,与IReadableCollection<string>
不同)之后,我原本期望添加一个新元素。
https://msdn.microsoft.com/en-us/library/system.array.aspx#Remarks
我从这里发现了 数组类显式实现IList.Add(Object)
和调用此方法始终抛出NotSupportedException异常。
这是第一次调用抛出错误原因的解释吗?
如果是这样,是否可以假设Add
是Array
类中的一种方法,它覆盖了来自Add
的{{1}}方法? (覆盖关键字而不是新的)
例如如果它是一种新方法而不是覆盖,那条线就不会抛出错误,是吗?
其次,这种情况的原因是:在预期通常可修改的集合IList
(与ICollection<T>
相对)中,我们有一个名为IReadableCollection<T>
的属性?
感谢您的澄清。
答案 0 :(得分:1)
投射某些东西并没有神奇地改变它以拥有该东西的所有方法。数组仍然是一个数组;当你想要阅读某些内容而不是修改它时,通常会进行转换。无论如何,从可维护性/易读性的角度来看,它是不合需要的。如果你想要一个可变的集合,这就是你可能正在寻找的东西:
string[] week = new string[] { "Monday", "Tuesday", "wednesday", "Saturday", "Sunday"};
var coll = week.ToList();
coll.Add("SlaveDay");
答案 1 :(得分:0)
是的,NotSupportedException可能是你通过调用从数组中铸造的ICollection中的Add方法获得的异常。
可以假设Add是Array类中的一个方法,它覆盖了IList的Add方法吗?
数组类没有“覆盖”来自IList的Add,因为IList是一个接口,而Array是一个类。类实现接口只是为了“遵守”接口的契约。
在C#中(不确定其他语言)可以explicitly implement接口方法。通过这样做,只有在保存带有接口类型的变量时才能使用实现的方法,这就是为什么在将数组转换为ICollection时只能看到“Add”方法的原因。
数组类可能有一行实现,用于抛出NotSupportException
。
是这种情况的原因:在预期通常可修改的集合ICollection(与IReadableCollection相对)中,我们有一个名为IsReadOnly的属性?
IList界面已经很老了,我不确定在那里添加这个属性的目的是什么。如果你打算有一个实现IList的类无法更改,我会建议反对它。有一个名为接口隔离原则(我在SOLID中)的概念,因此如果您需要实现一个只读的集合,理想情况下应该实现一个没有添加新项的方法的接口。
这个IsReadOnly
的一个很好的用法是在IList
的实现中指明一个状态,因此根据某些内容(例如列表中的项目数量),您可以指示您的列表处于读取状态只有国家。