【问题标题】:Determining the object type which send as parameter确定作为参数发送的对象类型
【发布时间】:2017-09-29 22:21:43
【问题描述】:

我有三个类,分别称为 Person、City 和 District,以及其他一些类。

我将这三个类之一作为函数参数发送。我想做一个操作取决于这三个中的哪一个已经发送。我怎样才能做到这一点?所有这三个类都扩展了一个实体类。

现在是这样的:

public void Insert (City newCity)

但我希望它是这样的:

public void Insert (Entity e)

或类似的东西,无论是什么(城市或人),我都想使用它的属性。

谢谢!

【问题讨论】:

  • 假设多态是不可能的(即e.DoTheThing(...);),那么可能是if(e is City) {...} else if (e is Person) {...} else if (e is District) {...} ?
  • 在没有更多代码的情况下,有点难以猜出你在这里做什么。但请查看 isas 运算符以确定您正在处理的类型/类的类型。
  • 为什么不直接使用Insert 的三个重载?对方法的参数进行类型检查似乎很奇怪,而不仅仅是为每个实体使用不同的方法......
  • @Christian.K 我正在简单地制作一个具有分层架构的数据库应用程序,只是为了学习。而在Presentation层,如果用户想添加一个Person,我会从用户那里获取信息并将它们用于业务和数据层。并确定它是哪个实体并在数据层中使用它以将其添加到数据库中。
  • @Chris 我想过,但是,我至少有 4 个操作,例如更新、删除、选择等。如果我也对其他方法使用重载,会不会有点复杂?另外,我想学习我问的方式。

标签: c#


【解决方案1】:

你可以让它通用:

public void Insert<T>(T entity) where T: Entity
{

}

现在您可以使用Entity 的所有属性或方法。如果需要使用只属于子类型的属性或方法,则必须强制转换:

public void Insert<T>(T entity) where T: Entity
{
    if(entity is City)
    {
        City city = (City) entity;
        // ...
    }
    else if(entity is Person)
    {
        Person person = (Person) entity;
        // ...
    }
}

【讨论】:

  • 很好的解决方案,但是 op 想要访问它们的属性,这些属性不会像这样工作,你需要强制转换。至少我是这么理解的
  • @EpicKip :除非重载方法,否则除了强制转换之外别无选择。虽然选角有什么问题??
  • @VisualVincent 嗯...因为首先它只说你可以让它通用,这不是完整的修复。现在帖子已经更新,它涵盖了所有内容。我是说没有涵盖演员阵容
  • 是的。我会尽快尝试这个和其他一些解决方案,然后我会通知你。谢谢!
【解决方案2】:

这样使用isas 运算符即可:

public void Insert(Entity e)
{
    if (e is Person)
    {
        Person tmp = e as Person;
        //do your code
    }
    else if (e is City)
    {
        City tmp = e as City;
        //do your code
    }
    else if(e is District)
    {
        District tmp = e as District;
        //do your code
    }
}

【讨论】:

    【解决方案3】:

    一种方法是使用继承和强制转换,如下所示:

            public abstract class Entity
            {
                public int Id { get; set; }
            }
    
            public class City : Entity
            {
                public string CityName { get; set; }
            }
    
            public class Person : Entity
            {
                public string PersonName { get; set; }
            }
    
            public class MethodHost
            {
                public void Insert(Entity e)
                {
                    if (e is Person person)
                    {
                        // Do something with person
                    } else if (e is City cityName)
                    {
                        // Do something with city
                    }
                }
            }
    

    P.S.:我在这里使用了一些新的 C# 功能,如果您使用的是旧版本的 C#,您可能需要执行以下操作:

    var city = e as city
    if(city != null)
    {
        // Do something with city
    }
    

    您也可以在 if 中使用 is 并在 if-tags 中强制转换 - 但这不是最高效的方式,因为它会强制转换两次而不是一次。

    【讨论】:

      【解决方案4】:

      最好的方法是实施不同的方法。如果他们内部有一些通用逻辑,只需将其带到不同的方法并调用它。

      public void Insert (City newCity)
      {
          // TODO logic for City
      }
      
      public void Insert (Entity e)
      {
          // TODO logic for Entity
      }
      

      另一种方法是继承。如果 City 可以从 Entity 派生,那么最好这样做:

      public class Entity 
      {
          public virutal void Insert (Entity e)
          {
              // TODO logic for Entity
          }
      }
      
      public class City : Entity
      {
          public override void Insert (City city)
          {
              // TODO logic for City
          }
      }
      

      【讨论】:

        【解决方案5】:

        在 C# 7.0 中,您可以使用模式匹配

        public void Insert(Entity e)
        {
            switch (e)
            {
                case Person p:
                    Console.WriteLine("Insert Person");
                    break;
                case City c:
                    Console.WriteLine("Insert City");
                    break;
        
                default:
                    Console.WriteLine("<other>");
                    break;
            }
        }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2016-07-10
          • 1970-01-01
          • 1970-01-01
          • 2016-12-05
          • 1970-01-01
          • 2012-05-29
          • 1970-01-01
          相关资源
          最近更新 更多