【问题标题】:Checking if the object is of same type检查对象是否属于同一类型
【发布时间】:2023-04-09 23:02:01
【问题描述】:

您好,我需要知道如何在 C# 中检查相同类型的对象。

场景:

class Base_Data{}

class Person : Base_Data { }
class Phone  : Base_data { }

class AnotherClass
{
   public void CheckObject(Base_Data data)
   {
         if (data.Equals(Person.GetType()))
         { //<-- Visual Studio 2010 gives me error, says that I am using 'Person' is a type and not a variable.

        }
    }
}

【问题讨论】:

  • 恕我直言:请重新考虑这种设计。您的方法要么适用于Base_Data 类型,要么适用于子类PersonPhone。如果CheckObject 发生了真正不同的事情,为什么不重载该方法并使用单独的CheckObject(Phone phone)CheckObject(Person person) 方法呢?这不是更多的代码,您会得到一些编译时间来检查您传递给CheckObjectBase_Data 子类是否受CheckObject 的支持。

标签: c# object


【解决方案1】:

你可以使用is operator:

if (data is Person)
{
    // `data` is an instance of Person
}

另一种可能是使用as operator:

var person = data as Person;
if (person != null)
{
    // safely use `person` here
}

或者,从 C# 7 开始,使用结合上述两者的pattern-matching form of the is operator

if (data is Person person)
{
    // `data` is an instance of Person,
    // and you can use it as such through `person`.
}

【讨论】:

  • 第二个例子中是否应该抛出异常是假的?如果是的话是什么类型的?
  • @jth41 对于该行为,只需使用常规转换 (Person person = (Person)data;) 而不是安全转换。
【解决方案2】:

这完全取决于您所追求的。使用isas(如Darin 的回答所示)将告诉您data 是指Person 的实例还是子类型。这是最常见的形式(尽管如果您可以在不需要它的情况下进行设计,那就更好了) - 如果这是您需要的,Darin 的答案就是使用方法。

但是,如果您需要 精确 匹配 - 如果您不想采取特定操作,如果 data 指的是从 Person 派生的某个类的实例,仅适用于 @ 987654327@ 本身,你需要这样的东西:

if (data.GetType() == typeof(Person))

这种情况比较少见——此时绝对值得质疑您的设计。

【讨论】:

  • 是否可以在 switch 中实现类类型检查?还是只有ifelse if
  • @Pierre:从 C# 7 开始,您可以在 switch 语句中使用模式,包括类型模式。
【解决方案3】:

让我们一次解决这个问题。第一步是必需的,接下来的两个是可选的,但建议使用。

第一次更正(这是必需的)确保您没有将某种类型的对象与System.Type 类型的对象进行比较:

if (data.GetType().Equals(typeof(Person))) ...
//      ^^^^^^^^^^
//      add this to make sure you're comparing Type against Type, not
//      Base_Data against Type (which caused the type-check error)!

其次,将其简化为:

if (data is Person) ... // this has (almost) the same meaning as the above;
                        // in your case, it's what you need.

第三,彻底摆脱if声明!这是通过使用多态性(或更准确地说,方法覆盖)来完成的,例如如下:

class Base_Data
{
    public virtual void Check() { ... }
}

class Person : Base_Data
{
    public override void Check()
    {
        ... // <-- do whatever you would have done inside the if block
    }
}

class AnotherClass
{
    public void CheckData(Base_Data data)
    {
         data.Check();
    }
}

如您所见,条件代码已转移到Base_Data 类及其派生类PersonCheck 方法中。不再需要这种类型检查 if 声明!

【讨论】:

    【解决方案4】:

    这个问题的意图有点不清楚,但我发现这个问题是在寻找一种方法来检查 2 个对象是否属于同一类型。这是我的解决方案和一些都通过的测试:

    using NUnit.Framework;
    
    [TestFixture]
    public class TypeEqualityChecks
    {
        class Base_Data { }
    
        class Person : Base_Data { }
        class Phone  : Base_Data { }
    
        class AnotherClass
        {
            public static bool CheckObjects(Base_Data d1, Base_Data d2) {
                return d1.GetType() == d2.GetType();
            }
        }
        
        [Test]
        public static void SameTypesAreEqual() {
            Base_Data person1 = new Person();
            Base_Data person2 = new Person();
            Assert.IsTrue(AnotherClass.CheckObjects(person1, person2));
        }
        
        [Test]
        public static void DifferentActualTypesAreNotEqual() {
            Base_Data person = new Person();
            Base_Data phone = new Phone();
            Assert.IsFalse(AnotherClass.CheckObjects(person, phone));
        }
        
        [Test]
        public static void BaseTypeAndChildTypeAreNotEqual() {
            Base_Data baseData = new Base_Data();
            Base_Data person = new Person();
            Assert.IsFalse(AnotherClass.CheckObjects(baseData, person));
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-01-13
      • 1970-01-01
      • 2021-03-06
      • 1970-01-01
      • 1970-01-01
      • 2022-01-25
      相关资源
      最近更新 更多