在规划我的程序时,我经常从一连串的想法开始:
足球队只是一个足球运动员名单.因此,我应该代表它:
Run Code Online (Sandbox Code Playgroud)var football_team = new List<FootballPlayer>();此列表的顺序表示球员在名单中列出的顺序.
但我后来才意识到,除了仅仅是球员名单之外,球队还有其他属性,必须记录下来.例如,本赛季的总得分,当前预算,统一颜色,string代表球队名称等等.
那么我认为:
好吧,足球队就像一个球员名单,但另外,它有一个名称(a
string)和一个总分(aint)..NET不提供用于存储足球队的类,所以我将创建自己的类.最相似和相关的现有结构是List<FootballPlayer>,所以我将继承它:Run Code Online (Sandbox Code Playgroud)class FootballTeam : List<FootballPlayer> { public string TeamName; public int RunningTotal }
但事实证明,指南说你不应该继承List<T>.我在两个方面完全被这个指南搞糊涂了.
显然List是以某种方式针对性能进行了优化.怎么会这样?如果我延长会给我带来什么性能问题List?究竟会打破什么?
我看到的另一个原因List是微软提供的,我无法控制它,所以我在以后暴露"公共API"后无法改变它.但我很难理解这一点.什么是公共API,我为什么要关心?如果我当前的项目没有并且不太可能拥有此公共API,我可以放心地忽略此指南吗?如果我继承List 并且事实证明我需要一个公共API,那么我将遇到什么困难?
为什么它甚至重要?列表是一个列表.什么可能改变?我可能想要改变什么?
最后,如果微软不想让我继承List,他们为什么不上课sealed呢?
显然,对于自定义集合,Microsoft提供了一个Collection应该扩展的类而不是List.但这个类是非常裸露,并没有多少有用的东西,比如AddRange,例如.jvitor83的答案提供了该特定方法的性能原理,但是如何缓慢AddRange而不是没有AddRange?
继承Collection是比继承更多的工作List,我认为没有任何好处.当然微软不会告诉我无缘无故地做额外的工作,所以我不禁觉得我在某种程度上误解了某些东西,而继承Collection实际上并不是解决我问题的正确方法.
我见过如实施的建议IList …
一位同事今天问我如何为一个系列添加一个范围.他有一个继承自的课程Collection<T>.这种类型的get-only属性已包含一些项目.他想将另一个集合中的项目添加到属性集合中.他怎么能以C#3友好的方式这样做呢?(注意关于get-only属性的约束,这会阻止像执行Union和重新分配这样的解决方案.)
当然,与物业的foreach.添加将工作.但是A List<T>风格的AddRange会更加优雅.
编写扩展方法很容易:
public static class CollectionHelpers
{
public static void AddRange<T>(this ICollection<T> destination,
IEnumerable<T> source)
{
foreach (T item in source)
{
destination.Add(item);
}
}
}
Run Code Online (Sandbox Code Playgroud)
但我感觉我正在重新发明轮子.我没有发现任何类似System.Linq或morelinq.
糟糕的设计?只需致电添加?缺少明显的?
我曾经读过Imaar Spaanjars关于如何构建3层应用程序的文章.(http://imar.spaanjaars.com/416/building-layered-web-applications-with-microsoft-aspnet-20-part-1)这已成为我编码的基础.
因此,我通过继承a来实现集合List<T>.因此,如果我有一个名为Employee的类,要实现一个集合,我还将有一个Employees类,如下所示.
class Employee
{
int EmpID {get;set;}
string EmpName {get;set;}
}
class Employees : List<Employee>
{
public Employees(){}
}
Run Code Online (Sandbox Code Playgroud)
我从来没有真正质疑这一点,因为它为我做了工作.但是现在我开始尝试一些事情,我不确定这是否是正确的方法.
例如,如果我想从Employees获得一个子集,例如
Employees newEmployees = (Employees) AllEmployees.FindAll(emp => emp.JoiningDate > DateTime.Now);
Run Code Online (Sandbox Code Playgroud)
这会抛出System.InvalidCastException.但是,如果我使用以下内容则没有问题.
List<Employee> newEmployees = AllEmployees.FindAll(emp => emp.JoiningDate > DateTime.Now);
Run Code Online (Sandbox Code Playgroud)
那么我该如何实现Employees以便我不必List<Employee>在DAL或BLL中明确使用?或者我怎么摆脱InvalidCastexception?
最近我使用了一个继承自集合的类,而不是在类中实例化集合,这是否可以接受,还是会在未来的路上产生看不见的问题?以下示例为了清楚起见:
public class Cars : List<aCar>
Run Code Online (Sandbox Code Playgroud)
而不是像:
public class Cars
{
List<aCar> CarList = new List<aCar>();
}
Run Code Online (Sandbox Code Playgroud)
有什么想法吗?
我有一个基本的集合类,它只包含一个自定义对象的列表,保存在List变量中以允许我使用this []索引.
但是,我现在想要使类可以从集合 LINQ查询中的项运行
使用简化的类比,我可以通过刚刚从列表中获得一名工作人员
Employeex = MyStaffList[Payroll];
Run Code Online (Sandbox Code Playgroud)
......但我现在想做的是
var HREmps = from emp in StaffList
where emp.Department == "HR"
select emp;
Run Code Online (Sandbox Code Playgroud)
下面是原型类定义....
public class StaffList
{
List<Employee> lst = new List<Employee>();
public StaffList()
{
/* Add Employees to the list */
}
public Employee this[string payroll]
{
get
{
Employee oRet = null;
foreach (Employee emp in lst)
{
if (emp.Payroll.Equals(payroll, StringComparison.InvariantCultureIgnoreCase))
{
oRet = emp ;
break;
}
}
return (oRet);
}
}
}
public …Run Code Online (Sandbox Code Playgroud) 我想实现一个优先级队列类.当以更高的优先级添加项目时,它将被推送到队列的前面,而不是添加到队列的末尾.
简单的几行代码
Public Class PriorityQueue(Of T)
Inherits List(Of T)
Private _list As New List(Of T)
Public Sub Enque(ByVal item As T, Optional ByVal pushToFront As Boolean = False)
If pushToFront = True Then
_list.Insert(0, item)
Else
_list.Add(item)
End If
End Sub
Public Function Deque() As T
If _list.Count <> 0 Then
Dim item As T = _list(0)
_list.RemoveAt(0)
Return item
Else
Throw New InvalidOperationException
End If
End Function
End Class
Run Code Online (Sandbox Code Playgroud)
现在调用函数试图找到队列中的元素....
dim _q as new PriorityQueue(Of integer)
_q.Enque(1)
_q.Enque(2)
msgbox(_q.Count()) …Run Code Online (Sandbox Code Playgroud) 我们假设这个类在C#中:
public class LimitedList<T> : List<T>
{
private int _maxitems = 500;
public void Add(T value) /* Adding a new Value to the buffer */
{
base.Add(value);
TrimData(); /* Delete old data if lenght too long */
}
private void TrimData()
{
int num = Math.Max(0, base.Count - _maxitems);
base.RemoveRange(0, num);
}
}
Run Code Online (Sandbox Code Playgroud)
编译器在"public void Add(T value)"行中给出了这个警告:
警告CS0108:'System.LimitedList.Add(T)'隐藏继承的成员'System.Collections.Generic.List.Add(T)'.如果要隐藏,请使用new关键字.
我该怎么做才能避免这种警告?
谢谢你的帮助
假设我有一个抽象基类:
public abstract class BaseClass
{
private MyObject myObject;
protected MyObject PropA
{
get
{
if(myObject == null) this.myObject = new MyObject();
return this.myObject;
}
}
}
Run Code Online (Sandbox Code Playgroud)
...在我的派生类之一中,我想将受保护的基类属性设为PropA public。在这种情况下使用new修饰符是否正确?
public class DerivedClass : BaseClass
{
public new MyObject PropA
{
get
{
return base.PropA;
}
}
}
Run Code Online (Sandbox Code Playgroud) 嗨,我想创建自定义集合,我从CollectionBase类派生我的自定义集合类,如下所示:
public class MyCollection : System.Collectio.CollectionBase
{
MyCollection(){}
public void Add(MyClass item)
{
this.List.Add(item);
}
}
class MyClass
{
public string name;
}
Run Code Online (Sandbox Code Playgroud)
我来问几个问题:
我有一个继承自的类Dictionary<string, string>.在一个实例方法中,我想迭代所有KeyValuePair<string, string>的.我尝试过以下方法:
foreach (KeyValuePair<string, string> pair in base)
Run Code Online (Sandbox Code Playgroud)
但是这失败了以下错误:
在此上下文中使用关键字"base"无效
如何KeyValuePair<string, string>在派生自的类中的实例方法中迭代Dictionary<string, string>?
编辑: 我发现我可以执行以下操作:
var enumerator = base.GetEnumerator();
while (enumerator.MoveNext())
{
KeyValuePair<string, string> pair = enumerator.Current;
}
Run Code Online (Sandbox Code Playgroud)
但是,我仍然想知道是否有办法通过foreach循环来做到这一点.
编辑: 感谢有关不继承的建议Dictionary<string, string>.我正在实施System.Collections.IEnumerable, ICollection<KeyValuePair<string, string>>, IEnumerable<KeyValuePair<string, string>>, IDictionary<string, string>.
c# ×9
inheritance ×5
list ×4
.net ×3
collections ×2
c#-3.0 ×1
class ×1
datagridview ×1
dictionary ×1
foreach ×1
generics ×1
linq ×1
oop ×1
vb.net ×1
wcf ×1