C# 接口与泛型类型相互引用
C# Interfaces with Generic Types Referencing One Another
目前我正在处理很多 classes 和那些 classes 的列表。以前我 有 静态方法,这些方法将采用特定的 class 列表和 return 列表的子集或单个项目。
但是我认为让 classes 继承 List 并在那里拥有必要的方法并且不再使它们成为静态的会更方便,因此它们适用于您正在使用的任何对象列表。
我一直无法找到一种简单的方法将列表转换为继承此列表的 class,因此我在所有这些集合 class 中创建了一个方法来为我转换它.
示例:
public class Student
{
public int Id {get;set;}
public string Name {get;set;}
}
public class Students : List<Student>
{
public Student GetTopStudent()
{
return this.OrderByDescending(s => s.Grade).FirstOrDefault();
}
public Students GetPassingStudents()
{
return this.Where(s => s.Grade > 0.7).ToCollection();
}
public Students ToCollection(IEnumerable<Student> studentsList)
{
var students = new Students();
foreach(var s in studentsList)
{
students.Add(s);
}
return students();
]
}
我还有许多其他 classes 和 classes 的列表,但这是一个非常简单的示例。我发现我的一些方法,比如 "ToCollection()" 方法在 class 之间实际上是相同的,除了 return 类型和列表中包含的类型。
所以我尝试创建扩展和接口来自动处理这些方法。
集合Class和接口
public abstract class Collection<T> : List<T>
{
// Needed tie in the extension method with the List.Add() Method
public void Add(object item) => base.Add((T)item);
}
public interface IObjectWithId<T>
where T : IObjectWithId<T>
{
int Id {get;set;}
}
public ICollectionItem<C>
where C : Collection<IcollectionItem<C>>
{
}
public ICollectionItemWithId<C,T>
where C : Collection<ICollectionItemWithId<C,T>>
where T : IObjectWithId<T>
{
}
扩展程序
public static List<T> Get<T>(this IEnumerable<IobjectWithId<T>> list, List<int> ids)
where T : IObjectWithId<T>
{
return list.Where(i => ids.Contains(i.Id))
.Cast<T>();
.ToList();
}
public static C Get<C, T>(this IEnumerable<IcollectionItemWithId<C, T>> list, List<int> ids)
where C : Collection<ICollectionItemWithId<C, T>>, new()
where T : IObjectWithId<T>
{
return list.Where(i => ids.Contains(i.Id)).ToCollection();
}
public static C ToCollection<C, T>(this IEnumerable<ICollectionItemWithId<C, T>> list)
where C : Collection<ICollectionItemWithId<C, T>>, new()
where T : IObjectWithId<T>
{
var collection = new C();
foreach(var item in list)
{
collection.Add(item);
}
return collection;
}
public static C ToCollection<C>(this IEnumerable<ICollectionItem<C>> list)
where C : Collection<ICollectionItem<C>>, new()
{
var collection = new C();
foreach(var item in list)
{
collection.Add(item);
}
return collection;
}
我无法使此代码正常工作。通常我在构建它后会出错,要么没有从学生 class 到学生列表的隐式引用转换,要么是与装箱有关的错误。
我担心我的接口相互引用可能会产生很多问题,但是我这样做的原因是我不必指定方法的 return 类型,尽管也许这将是目前最简单的事情...
你把事情复杂化了。根本问题是你奇怪的自我引用 public interface IObjectWithId<T>
。由于您不在界面本身的任何地方使用 T 这不需要是通用的。
只需编写适用于 IEnumerable<T>
和 return IEnumerable<T>
的扩展方法,并对 T 进行一些简单的约束,例如
// This does not need to be generic in any way
public interface IObjectWithId
{
int Id {get;set;}
}
public static IEnumerable<T> Get<T>(this IEnumerable<T> list, List<int> ids)
where T : IObjectWithId
{
return list.Where(i => ids.Contains(i.Id));
}
如果他们愿意,让调用者链接 .ToList()
到此。有时他们可能只想要一个(Single()
或 First()
),或者他们可能会在它之后执行另一个过滤器或组操作,因此将其强制返回 List<T>
是低效的。
目前我正在处理很多 classes 和那些 classes 的列表。以前我 有 静态方法,这些方法将采用特定的 class 列表和 return 列表的子集或单个项目。
但是我认为让 classes 继承 List 并在那里拥有必要的方法并且不再使它们成为静态的会更方便,因此它们适用于您正在使用的任何对象列表。
我一直无法找到一种简单的方法将列表转换为继承此列表的 class,因此我在所有这些集合 class 中创建了一个方法来为我转换它.
示例:
public class Student
{
public int Id {get;set;}
public string Name {get;set;}
}
public class Students : List<Student>
{
public Student GetTopStudent()
{
return this.OrderByDescending(s => s.Grade).FirstOrDefault();
}
public Students GetPassingStudents()
{
return this.Where(s => s.Grade > 0.7).ToCollection();
}
public Students ToCollection(IEnumerable<Student> studentsList)
{
var students = new Students();
foreach(var s in studentsList)
{
students.Add(s);
}
return students();
]
}
我还有许多其他 classes 和 classes 的列表,但这是一个非常简单的示例。我发现我的一些方法,比如 "ToCollection()" 方法在 class 之间实际上是相同的,除了 return 类型和列表中包含的类型。
所以我尝试创建扩展和接口来自动处理这些方法。
集合Class和接口
public abstract class Collection<T> : List<T>
{
// Needed tie in the extension method with the List.Add() Method
public void Add(object item) => base.Add((T)item);
}
public interface IObjectWithId<T>
where T : IObjectWithId<T>
{
int Id {get;set;}
}
public ICollectionItem<C>
where C : Collection<IcollectionItem<C>>
{
}
public ICollectionItemWithId<C,T>
where C : Collection<ICollectionItemWithId<C,T>>
where T : IObjectWithId<T>
{
}
扩展程序
public static List<T> Get<T>(this IEnumerable<IobjectWithId<T>> list, List<int> ids)
where T : IObjectWithId<T>
{
return list.Where(i => ids.Contains(i.Id))
.Cast<T>();
.ToList();
}
public static C Get<C, T>(this IEnumerable<IcollectionItemWithId<C, T>> list, List<int> ids)
where C : Collection<ICollectionItemWithId<C, T>>, new()
where T : IObjectWithId<T>
{
return list.Where(i => ids.Contains(i.Id)).ToCollection();
}
public static C ToCollection<C, T>(this IEnumerable<ICollectionItemWithId<C, T>> list)
where C : Collection<ICollectionItemWithId<C, T>>, new()
where T : IObjectWithId<T>
{
var collection = new C();
foreach(var item in list)
{
collection.Add(item);
}
return collection;
}
public static C ToCollection<C>(this IEnumerable<ICollectionItem<C>> list)
where C : Collection<ICollectionItem<C>>, new()
{
var collection = new C();
foreach(var item in list)
{
collection.Add(item);
}
return collection;
}
我无法使此代码正常工作。通常我在构建它后会出错,要么没有从学生 class 到学生列表的隐式引用转换,要么是与装箱有关的错误。
我担心我的接口相互引用可能会产生很多问题,但是我这样做的原因是我不必指定方法的 return 类型,尽管也许这将是目前最简单的事情...
你把事情复杂化了。根本问题是你奇怪的自我引用 public interface IObjectWithId<T>
。由于您不在界面本身的任何地方使用 T 这不需要是通用的。
只需编写适用于 IEnumerable<T>
和 return IEnumerable<T>
的扩展方法,并对 T 进行一些简单的约束,例如
// This does not need to be generic in any way
public interface IObjectWithId
{
int Id {get;set;}
}
public static IEnumerable<T> Get<T>(this IEnumerable<T> list, List<int> ids)
where T : IObjectWithId
{
return list.Where(i => ids.Contains(i.Id));
}
如果他们愿意,让调用者链接 .ToList()
到此。有时他们可能只想要一个(Single()
或 First()
),或者他们可能会在它之后执行另一个过滤器或组操作,因此将其强制返回 List<T>
是低效的。