【问题标题】:How to check if object is of any of given types in C#如何检查对象是否属于C#中的任何给定类型
【发布时间】:2023-03-24 11:34:01
【问题描述】:

我正在使用 Unity Engine,其中有一个基类 Component 和从它派生的多个类,包括 TransformMeshRenderer 和我创建的许多类。

我想执行一个动作(在这种情况下 Destroy 所有非类型的组件:TransformMeshRendererMeshFilterColliderBuildMenuItem)。我的基本方法如下所示:

Component[] components = obj.GetComponents<Component>();
foreach (var component in components) {
    if (component is MeshFilter)
        continue;
    if (component is MeshRenderer)
        continue;
    if (component is Transform)
        continue;
    if (component is Collider)
        continue;
    if (component is BuildMenuItem)
        continue;

    Destroy(component);
}

在我看来,它看起来很难看,我发现缩短它的唯一方法是使用 || 运算符,但它并不能解决很多问题,而且 IMO 看起来更糟。有没有更简洁的实现方式?

【问题讨论】:

标签: c# .net code-cleanup


【解决方案1】:

您可以初始化Types 的集合(例如List&lt;Type&gt;HashSet&lt;Tepe&gt; 等),将所有需要的类型添加到其中(typeof(Transform),...),然后使用Contains 来检查组件类型是否在该集合中。

var types = new HashSet<Type> {typeof(Transform), typeof(MeshRenderer)};

Component[] components = obj.GetComponents<Component>();
foreach (var component in components.Where(c => !types.Contains(c.GetType())))
{
    Destroy(component);
}

更新:

Type[] types = { typeof(Transform), typeof(MeshRenderer) };

Component[] components = obj.GetComponents<Component>();
foreach (var component in components.Where(c => !types.Any(x => c.GetType().IsAssignableFrom(x))))
{
    Destroy(component);
}

【讨论】:

  • 不幸的是,这不包括派生类(例如,派生自 ColliderBoxCollider 在您的方法中被破坏,而不是在原始方法中)
  • 如何将 lambda 修改为 c =&gt; !types.Any(x =&gt; c.GetType().IsAssignableFrom(x)).edit 刚刚看到编辑。
  • @Immorality,好点,IsAssignableFrom更适合这里
【解决方案2】:

创建一个接口INotDestroyable,使不可破坏的类型TransformMeshRendererMeshFilterColliderBuildMenuItem实现它,然后在你的循环中检查元素是否没有实现它。接口不必定义任何属性或成员。

【讨论】:

  • 这是个好主意,但就我的需要而言,它太……“恒定”。我可能想要另一个过滤其他类型的函数,所以我需要为每个类型创建多个接口。虽然它不符合我的需求,但它仍然具有很大的价值
  • 另外,很多提到的类都是 Unity 类,因此不可编辑。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-09-12
  • 2010-09-23
  • 2018-07-10
  • 2015-02-19
  • 2011-03-25
相关资源
最近更新 更多