从Java到c# -泛型强制转换为BaseClass

本文关键字:转换 BaseClass 泛型 Java | 更新日期: 2023-09-27 18:17:14

我目前有一个泛型的问题。我想把现有的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();
        }
    }
}

列表应该包含各种模块对象,其中值字段本身可以有各种类型,但它们都继承BasicData。我找了一会儿,但我只找到了奇异的解决办法。在c#中没有简单的方法来做类似的事情吗?我不想重写我的整个设计。

一开始我想我可以像这样在c#中声明列表:

LinkedList<Modul<BasicData>> collection;
void add(Modul<BasicData> m)
{
     this.dataCollection.add(m);
}

,然后添加各种对象,像这样:

class DataImpl : Modul<int>
{
}
handler.add(new DataImpl());

但是我发现你不能强制转换这个模块。有解决办法吗?

提前感谢,米克

从Java到c# -泛型强制转换为BaseClass

c#没有?Java的通配符机制——c#泛型中Java通配符的等价物是什么,所以这个问题没有直接的本地解决方案。

可能的解决方式:

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中),如果没有强制转换,您将无法以简单的方式访问不同的泛型-这不是处理放入一个集合中的不同数据类型的最佳方法。

您可以在c#中尝试相同的操作,如下所示:

public abstract class Module<T> where T : BasicData
{
}

我想我有一个解决办法。它把别人和你说过的话和这里没有提到的东西结合在一起。

如果你有class Foo

class Foo {
    public virtual void Method1() {
        //Do something
    }
    public void Method2() {
        //Do something
    }
    //class code
}
现在,你有了一个类Bar,它继承了Foo
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中的更多情况,如果清楚的话。此外,如果我错了,请纠正我