【问题标题】:Create different generic objects based on argument type in C#在 C# 中根据参数类型创建不同的泛型对象
【发布时间】:2020-08-26 01:56:58
【问题描述】:

假设我有许多(比如 10 个)类 A1、...、A10 的列表,它们都继承自基类 A,并且我有一个从它们到其他 10 个类 B1 的一对一映射,...,B10。我还有一个通用类MyClass<T> 我希望有一个函数Func(A a),如果输入是A1 的实例,它创建一个MyClass<B1> 实例,如果输入是一个实例,则创建一个MyClass<B2> 实例A2 等。我可以使用 switch 语句来做到这一点,但如果类的数量增加,它就会变得混乱。这样做的好方法是什么?

这是一个具体的例子:假设 A 类是 CatDog,B 类是 FooBar,我还有另一个 Generator 类来生成这些实例。

public class Generator{
    public Foo Generate(Cat c){ 
        // some code
    }
     
    public Bar Generate(Dog d){
        // some code
    }
}

我下面有一个通用类

public class MyClass<T>{
   private T _t; 

   public MyClass(T t){
       this._t = t; 
   }
}

现在在代码中我想做这样的事情

Generator gen = new Generator(); 
dynamic animal = new Dog(); 
var result = gen.Generate(animal); // can be of type Foo or Bar  
var cl = new MyClass(result); // does not compile!

最后一行没有编译,因为它缺少泛型类型参数。

如果需要更多详细信息,请告诉我!

【问题讨论】:

  • 你能分享一些代码来更好地了解你需要什么吗?即 A 类之一,B 类之一,以及您当前正在进行的映射?
  • 好主意——刚刚编辑了问题。
  • 你能分享MyClass的目的是什么吗?我知道现在的问题是由于泛型参数,它不能被实例化(至少不是很好)。该通用字段如何以及在何处使用?

标签: c# generics polymorphism


【解决方案1】:

每种类型的 A 都知道如何产生它对应的 B 吗?然后你不必有一个大的决策树在一些单独的代码中测试 A 的类型,然后创建 Bs...该代码只是调用 a.GetB()。

【讨论】:

  • 这样做会创建 Bs,但我仍然不明白如何创建泛型类?例如,假设 Myclass 有一个以 T 作为参数的构造函数,那么为了构造 MyClass B1 的实例,我应该在尖括号内放什么?
【解决方案2】:

请注意,在使用这样的动力学时,可能很难摆脱对上游动力学的使用。 要指定泛型参数,一种方法是创建一个可以推断类型的工厂方法:

namespace ConsoleApp13
{
    public class Program
    {
        public static void Main() {
            Generator gen = new Generator(); 
            dynamic animal = new Dog(); 
            var result = gen.Generate(animal); // can be of type Foo or Bar  
            var myClass = MyClass.Create(result);
        }
    }
    public static class MyClass
    {
        public static MyClass<T> Create<T>(T value) => new MyClass<T>(value);
    }
    public class Generator{
        public Foo Generate(Cat c){ 
            // some code
            return new Foo();
        }
     
        public Bar Generate(Dog d){
            // some code
            return new Bar();
        }
    }
    public class MyClass<T>{
        private T _t; 

        public MyClass(T t){
            this._t = t; 
        }
    }


    public class Dog
    {
    }

    public class Bar
    {
    }

    public class Cat
    {
    }

    public class Foo
    {
    }
}

但正如其他人所说,在这种情况下,如果您有 A 类创建 B 作为动态并且不再需要 Generator 类,则不需要这样做:

namespace ConsoleApp13
{
    public class Program
    {
        public static void Main() {
            var animal = new Dog();
            var myClassWithoutNewMethod = new MyClass<Bar>(animal.GetBar());
            var myClass = MyClass.Create(animal);
        }
    }
    public static class MyClass
    {
        public static MyClass<T> Create<T>(T value) => new MyClass<T>(value);
    }
    public class MyClass<T>{
        private T _t; 

        public MyClass(T t){
            this._t = t; 
        }
    }


    public class Dog
    {
        public Bar GetBar()
        {
            return new Bar();
        }
    }

    public class Bar
    {
    }

    public class Cat
    {
    }

    public class Foo
    {
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-06-27
    • 1970-01-01
    • 1970-01-01
    • 2014-04-04
    • 1970-01-01
    • 2013-05-17
    相关资源
    最近更新 更多