从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());
但是我发现你不能强制转换这个模块。有解决办法吗?
提前感谢,米克
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中的更多情况,如果清楚的话。此外,如果我错了,请纠正我