【问题标题】:From Java to C# - Generic cast to BaseClass从 Java 到 C# - 泛型转换为 BaseClass
【发布时间】:2014-08-08 17:02:10
【问题描述】:

我目前对泛型有疑问。我想将现有的 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());

但我发现你不能施放这个 Modul。 有解决办法吗?

提前致谢, 米克

【问题讨论】:

  • 能否请您显示演示“无法转换此模块”的代码?还要发布 BasicDataModul&lt;T&gt; 的 C# 定义,因为不清楚您尝试了什么。

标签: java c# generics


【解决方案1】:

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

【讨论】:

    【解决方案2】:

    您可以在 C# 中尝试相同的方法,如下所示:

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

    【讨论】:

    • +1,因为它可能是一个答案。另外我怀疑问题不在于那部分,而在于翻译 wildcard 类型(LinkedList&lt;Modul&lt;?&gt;&gt;),它在 C# 中没有直接等效项。
    • 感谢您的回复,但正如 alexei levenkov 已经提到的,问题是从 Module 到 Module 的转换
    • @mick 你欢迎老兄。为什么需要这种转换?我的意思是在抽象类的定义中使用T 参数,您定义了一个通用抽象类,您每次使用的类型都应该继承名为BasicData 的类。对吗?
    【解决方案3】:

    我想我为你找到了解决方案。它有点使用别人和你说的东西,并将它与这里没有提到的东西结合起来。

    如果你有类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;
            }
        }
    }
    

    如果清楚的话,还可以在 RelatedLinkedstackoverflow 中查看更多案例。此外,如果我在某个地方错了,请纠正我

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-12-25
      • 2015-11-17
      • 2011-06-29
      • 2014-07-13
      相关资源
      最近更新 更多