在基础 class 方法中使用未来的 subclass 类型
Use a future subclass type in a base class method
假设我有一个基础 class BaseFoo
和一个方法来处理完全由 BaseFoo 组成的数据结构:
public class BaseFoo { // FWIW, in my "real" example, this is an abstract base class
public void Func(IEnumerable<BaseFoo> data) {
// impl.
}
}
然后我有一些子classes, Bar
and Baz
:
public class Bar : BaseFoo {}
public class Baz : BaseFoo {}
但我意识到我对 Func
的参数包含所有相同类型的对象并且该类型与子 class 匹配非常重要!继承的Bar.Func
方法如果被传new[] {new Bar(), new Baz()}
.
,灾难可能降临
如何在 BaseFoo.Func
的声明中强制执行此操作? (我不能使用泛型 <T> where T : BaseFoo
,因为编译器只会将 BaseFoo
用于 T
,最后一段末尾的错误示例会编译。)
编辑:
也许是一个更好的例子:我想在我的 Bar
子 class 中存储 Bar
的列表,Baz
也是如此。但是我想在 FooBase
中为 List<this.GetType()>
写一个声明,我很清楚这不会编译。我只是在寻找一种在基础 class.
中使用任意子 class 类型 的方法
一种方法是使用 泛型
例子
public class BaseFoo<T> where T : BaseFoo<T>
{
public void Func(IEnumerable<T> data) { }
}
public class Bar : BaseFoo<Bar> {}
public class Baz : BaseFoo<Baz> {}
这意味着
var bar = new Bar()
bar.Func(new List<bar>()) // can only ever take an enumerable of bar
免责声明:这忽略了您在概念上或其他方面可能遇到的任何其他问题
更新
我已经添加了 where T : BaseFoo<T>
这被称为 Curiously recurring template pattern in C++, inspired by the comments from charlieface, also Eric Lippert has written about this in one of his blogs Curiouser and curiouser。
假设我有一个基础 class BaseFoo
和一个方法来处理完全由 BaseFoo 组成的数据结构:
public class BaseFoo { // FWIW, in my "real" example, this is an abstract base class
public void Func(IEnumerable<BaseFoo> data) {
// impl.
}
}
然后我有一些子classes, Bar
and Baz
:
public class Bar : BaseFoo {}
public class Baz : BaseFoo {}
但我意识到我对 Func
的参数包含所有相同类型的对象并且该类型与子 class 匹配非常重要!继承的Bar.Func
方法如果被传new[] {new Bar(), new Baz()}
.
如何在 BaseFoo.Func
的声明中强制执行此操作? (我不能使用泛型 <T> where T : BaseFoo
,因为编译器只会将 BaseFoo
用于 T
,最后一段末尾的错误示例会编译。)
编辑:
也许是一个更好的例子:我想在我的 Bar
子 class 中存储 Bar
的列表,Baz
也是如此。但是我想在 FooBase
中为 List<this.GetType()>
写一个声明,我很清楚这不会编译。我只是在寻找一种在基础 class.
一种方法是使用 泛型
例子
public class BaseFoo<T> where T : BaseFoo<T>
{
public void Func(IEnumerable<T> data) { }
}
public class Bar : BaseFoo<Bar> {}
public class Baz : BaseFoo<Baz> {}
这意味着
var bar = new Bar()
bar.Func(new List<bar>()) // can only ever take an enumerable of bar
免责声明:这忽略了您在概念上或其他方面可能遇到的任何其他问题
更新
我已经添加了 where T : BaseFoo<T>
这被称为 Curiously recurring template pattern in C++, inspired by the comments from charlieface, also Eric Lippert has written about this in one of his blogs Curiouser and curiouser。