有条件地创建不同类的对象

时间:2014-04-03 13:10:14

标签: c# class object dynamic types

我想用其他类来实现某些东西,但我会提供一个与我类似的例子。假设我们有以下类和enum性别:

public enum Gender
{
    Male = 1,
    Female = 2
}

public abstract class Human
{
    public string Name { get; set; }
}

public class Woman : Human
{
    public bool Intuition { get; set; }
}

public class Man : Human
{
    public bool Logic { get; set; }
}

让我们说我想要一个使用一组访问者(人类)的类会议,这些访问者可以是Man或Woman对象。该数组将包含两个类之一的对象,具体取决于提供的Gender枚举的值。所以,我可以这样做:

public class Meeting
{
    private Human[] visitors;
    public Human[] Visitors { get { return visitors; } set { visitors = value; } }

    public Meeting(Gender gender, int number)
    {
        if (gender == Gender.Male)
        {
            // If the gender is Male, create a new array of Man objects.
            visitors = new Man[number];
        }
        else
        {
            // Otherwise, create a new array of Woman objects.
            visitors = new Woman[number];
        }

        for (int i = 0; i < number; i++)
        {
            if (gender == Gender.Male)
            {
                // If the gender is Male, create a new Man object.
                visitors[i] = new Man();
            }
            else
            {
                // Otherwise, create a new Woman object.
                visitors[i] = new Woman();
            }
        }
    }
}

代码在语法上是正确的,但我认为它不是一个写得很好的代码。假设我不仅有女人和男人的课程,而且还有10个课程。此外,假设我没有两行,而是一千行代码,我应该创建一个新的类实例,具体取决于某些条件(在我的例子中是Gender枚举的值)。

有没有更好的方法来实现这一目标?例如,某种类/变量在方法的开头分配,取决于值(枚举),然后在其他地方使用。

我应该在这种情况下使用泛型吗?

4 个答案:

答案 0 :(得分:3)

我的解决方案

  • 我会使用通用工厂。这消除了对枚举类型的需要。添加工厂的另一个原因是,如果人工构造需要额外的工作,这可以在工厂完成,并且不会分散在解决方案的多个位置。
  • 我认为你的实例数组是一种特殊类型,但它可以是基类型。这消除了你的第一个if语句。无论如何,你将你的阵列暴露为人类阵列。
  • 添加一些LINQ以简化循环。

这导致以下结果:

public class HumanFactory {
    public T Create<T>() where T: Human, new() {
        return new T();
    }
}

public class Meeting<T> where T: Human {
    public T[] Visitors { get; set; }

    public Meeting(int number) {
        var humanFactory = new HumanFactory();
        Visitors = Enumerable.Range(1, number)
            .Select(x => humanFactory.Create<T>())
            .ToArray();
    }
}

答案 1 :(得分:1)

是的,这是使用泛型的好例子。你可以这样做:

public class Meeting<T> where T : Human, new()
{
    private T[] visitors;

    public T[] Visitors
    {
        get { return visitors; }
        set { visitors = value; }
    }

    public Meeting(int number)
    {
        visitors = new T[number];
        for (int i = 0; i < number; i++)
        {
            visitors[i] = new T();
        }
    }
}

如果你使用泛型,你也不会需要Gender枚举。这是用法:

Meeting<Man> m = new Meeting<Man>(10);

m.Visitors[0].Name = "Jack";

Console.WriteLine(m.Visitors[0].Name);

答案 2 :(得分:0)

不要混合多态性和枚举。它们都具有相同的目的,多态性是更开放/封闭的解决方案。

在这种情况下,我认为你的问题是你的抽象:

你的男人有逻辑,你的女人有直觉,你的抽象可能是ISolveProblem,男人的实施使用逻辑解决问题,女人使用他们的直觉。

这样,您不需要长切换或if / else语句(即10种可能性),但可以循环遍历数组并执行SolveProblem方法而不考虑实际的&#Type 39;人&#39;

答案 3 :(得分:0)

确保您的Enum成员名称与您的类名相同。你可以使用这种方法

 public enum Gender
    {
        Men,Women
    }
    public class Human
    { 
    }
    class Men : Human
    {
    }
    class Women : Human
    {
    }

    class Meeting
    {
        List<Human> visitors = new List<Human>();

        public Meeting(Gender m, int Number)
        {
            string ClassName ="YourNameSpace."+ m.ToString();
            Type type = Type.GetType(ClassName);
            object instance = Activator.CreateInstance(type);
            for(int i=0; i<Number; i++)
            {
            visitors.Add(instance as Human);
            }

        }

    }