【问题标题】:Conditionally create objects of different classes有条件地创建不同类的对象
【发布时间】:2014-05-15 08:23:06
【问题描述】:

我想通过其他类实现一些目标,但我将提供一个与我的类似的示例。假设我们有以下类和枚举 Gender:

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; }
}

假设我想要一个使用访问者数组(人类)的会议类,这些访问者可以是男人或女人对象。该数组将包含两个类之一的对象,具体取决于提供的 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();
            }
        }
    }
}

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

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

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

【问题讨论】:

    标签: c# class object dynamic types


    【解决方案1】:

    我的解决方案

    • 我会使用通用工厂。这消除了对枚举类型的需要。添加工厂的另外一个原因是,如果人的构建涉及额外的工作,这可以在工厂中完成,并且不会分散在您的解决方案中的多个地方。
    • 在我看来,您的实例化数组是一种特殊类型,但它可以是基本类型。这消除了您的第一个 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();
        }
    }
    

    【讨论】:

      【解决方案2】:

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

      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);
      

      【讨论】:

        【解决方案3】:

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

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

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

        这样,您不需要长的 switch 或 if/else 语句(即 10 种可能性),而是可以循环遍历数组并执行 SolveProblem 方法,而无需考虑“人类”的实际类型。

        【讨论】:

          【解决方案4】:

          通过确保 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);
                      }
          
                  }
          
              }
          

          【讨论】:

            猜你喜欢
            • 2023-04-01
            • 1970-01-01
            • 2017-10-12
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2017-10-11
            相关资源
            最近更新 更多