我目前在泛型方面存在问题。我想将现有的Java代码转移到c#中。任何人都可以告诉我,我怎样才能在c#中做到?
例如,我有一个名为module的类,它带有一个继承自basicdata的泛型参数。我想将许多这些对象添加到处理程序中,以便可以在单个方法中更新它们。
在java中我有这样的东西:
public class BasicData
{
}
public abstract class Modul<T extends BasicData>
{
T value;
abstract void update(); // do something with the value
}
public class Handler
{
LinkedList<Modul<?>> modulCollection = new LinkedList<Data<?>>();
void add(Modul<?> m)
{
this.dataCollection.add(m);
}
void update(){
for(Modul<?> d : this.modulCollection){
d.update();
}
}
}
列表应该包含各种模块对象,其中value字段本身可以有各种类型,但它们都继承了BasicData。 我搜索了一会儿,但我只找到了异国情调的解决方案。有没有简单的方法在c#中做类似的事情?我不想改写我的整个设计。
起初我以为我可以在c#中声明这样的列表:
LinkedList<Modul<BasicData>> collection;
void add(Modul<BasicData> m)
{
this.dataCollection.add(m);
}
然后添加如下所示的各种对象:
class DataImpl : Modul<int>
{
}
handler.add(new DataImpl());
但我发现你不能施放这个模块。 是否有解决办法做这样的事情?
提前谢谢, 米克答案 0 :(得分:2)
C#没有? Java具有的通配符机制 - What is the equivalent of Java wildcards in C# generics,因此没有针对此问题的直接原生解决方案。
可能的解决方案:
1。为Modul
使用基础非通用类或接口:
public abstract class ModulBase : BasicData
{
abstract void update(); // do something with the value
}
public abstract class Modul<T> : ModulBase ...
或
public interface IUpdateable
{
void Update();
}
public abstract class Modul<T> : BasicData, IUpdateable...
并使用它:
public class Handler
{
LinkedList<IUpdateable> modulCollection = new LinkedList<IUpdateable>();
void add<T>(Modul<T> m) // It is generic now
{
this.dataCollection.add(m);
}
void update(){
foreach (IUpdateable d in this.modulCollection){
d.update();
}
}
}
你的Handler.moduelCollection
不再是这种方法的通用,但在任何情况下(即使在Java中)你都无法以简单的方式访问不同的泛型而不进行强制转换 - 这不是最好的处理放入一个集合的不同数据类型的方法。
答案 1 :(得分:1)
您可以在C#中尝试相同的内容,如下所示:
public abstract class Module<T> where T : BasicData
{
}
答案 2 :(得分:0)
我想我找到了一个解决方案。它有点使用别人和你所说的,并把它与这里没有提到的东西结合起来。
如果您有课程 Foo
class Foo {
public virtual void Method1() {
//Do something
}
public void Method2() {
//Do something
}
//class code
}
现在,您有一个继承自 Foo
的 Bar 类class Bar : Foo {
public override void Method1() {
//Do something
}
public new void Method2() {
//Do something
}
//class code
}
如果您声明类 Bar 的变量并尝试将其转换为 Foo ,则完全可以接受并且您不会丢失任何数据。但是,下次要使用额外的属性,方法和变量时,需要将其转换回 Bar 。但是,如果普通成员是覆盖,它们的行为应该像是由 Bar 变量调用,否则,如果对象被克隆或向后转换,则公共成员的行为就像它们被调用一样通过 Foo 实例。
例如:
Bar myBar = new Bar();
Foo myFoo = myBar; //Now myFoo and myBar refer to the same memory address
Foo myFoo2 = myBar.Clone() as Foo; //myFoo2 and myBar do not refer to the same memory address
//These should do exactly the same thing because Method1 is an override
myBar.Method1();
myFoo.Method1();
//These should not do exactly the same thing unless Method2 was not changed in Bar
myBar.Method2();
myFoo.Method2();
//These should do exactly the same thing because Method1 is an override
myBar.Method1();
myFoo2.Method1();
//These should not do exactly the same thing unless Method2 was not changed in Bar
myBar.Method2();
myFoo2.Method2();
Bar myBarConvertedBack = (Bar)myFoo; //No data lost
现在回到这个问题。试试这个:
public abstract class Module<T> where T : BasicData {
protected T value;
public abstract void Update();
public virtual T Value {
get;
set;
}
}
public class Handler
{
LinkedList<Modul<BasicData>> modulCollection = new LinkedList<Data<BasicData>>();
pulic void Add(Modul<BasicData> m)
{
this.modulCollection.add(m);
}
public void Update() {
foreach (Modul<BasicData> d in this.modulCollection)
d.update();
}
}
将此类视为 Module :
中可能的派生类public class Class1: Module<BasicData> {
public Class1(BasicData val) {
base.value = val;
}
public override void Update() {
//Do something here
}
public override BasicData Value {
get {
return base.value;
}
set {
base.value = value;
}
}
}
如果清楚,请参阅相关或已链接中 stackoverflow 中的更多案例。此外,如果我错了某地纠正我