C# 如何询问数组是否包含特定类?

C# 如何询问数组是否包含特定类?,c#,arrays,methods,xna,contains,C#,Arrays,Methods,Xna,Contains,我正在尝试创建一个“马里奥”视频游戏,为了获得相交的对象,我们的老师为我们提供了一个示例演示,该演示允许对象检测它是否正好接触到另一个对象,并返回该方法找到的第一个对象。我尝试返回当前对象当前正在接触的每个对象的数组。我能够返回当前接触它的每个对象的数组,但现在我需要一种简单/高效的方法来检查数组是否包含所需类型的对象,例如 if (array.Contains(Mario)) { //Do Work here } 正在检查是否包含(Mario)的数组是相交精灵的返回数

我正在尝试创建一个“马里奥”视频游戏,为了获得相交的对象,我们的老师为我们提供了一个示例演示,该演示允许对象检测它是否正好接触到另一个对象,并返回该方法找到的第一个对象。我尝试返回当前对象当前正在接触的每个对象的数组。我能够返回当前接触它的每个对象的数组,但现在我需要一种简单/高效的方法来检查数组是否包含所需类型的对象,例如

if (array.Contains(Mario))
    {
    //Do Work here
    }

正在检查是否包含(Mario)的数组是相交精灵的返回数组,但当我询问它是否确实包含Mario类型的对象时,它会说“Error 14‘WindowsGame10.Mario’是一个‘类型’,但用作‘变量’”。我知道我可以使用for循环来实现这一点,并要求数组中的每个索引
if(array[I].GetType()==typeof(Mario))
,但是对于我需要在代码中执行此检查并反复重新键入相同代码的次数,我觉得我需要学习一种更有效的方法来执行此操作。我在计算机编程的第一年,我在C#XNA工作,我需要一些我能理解的解决方案。如果有更好的方法,请告诉我。

您可以使用LINQ的
of type()
Any()
方法:

if (array.OfType<Mario>().Any())
{
if(array.OfType().Any())
{
使用Linq,您可以执行以下操作:

var marios = array.OfType<Mario>();
if (marios.Any())
{
     //Stuff
}
var marios=array.OfType();
if(marios.Any())
{
//东西
}
最直接的方法(不使用LINQ)是使用
is
关键字:

foreach (Object obj in array)
{
    if (obj is Mario)
    {
        ...
    }
}
更新: 如果您需要一个精确的
类型
匹配,并且希望避免代码重复,我认为类似于此的非常简单的扩展方法是最好的-

public static bool ContainsType<T>(this T[] arr, Type type)
{
    for (int i = 0; i < arr.Length; i++)
        if (arr[i].GetType().Equals(type))
            return true;
    return false;
}

如果你只想知道有没有马里奥的话

if(array.Any(a=>a is Mario))
{
}

这将在找到第一个匹配项后立即中断迭代。

Linq答案非常好。为了提供另一种方法,您可以定义如下扩展方法:

static public bool ContainsType(this Array array, Type type)
{
    int len = array.Length; // Note that putting this in the loop is slightly slower
                            // because the compiler can't assume that a property value
                            // remains constant.
    for (int i = 0; i < len; i++)
    {
        if (array.GetValue(i).GetType() == type) return true;
    }

    return false;
}
    Array a = new object[] { "The meaning of life.", 42 };
    bool hasString = a.ContainsType(typeof(string)); // true
    bool hasInteger = a.ContainsType(typeof(int));  // true
    bool hasChar = a.ContainsType(typeof(char));  // false

您可以始终将该循环包装在一个方法中,以避免代码重复。谢谢。这大大减少了我可能使用的for循环的数量。请注意,在找到第一个匹配之前,您仍在遍历数组,或者在没有匹配的情况下遍历整个数组。Linq是一个很好的抽象,可以减少编程工作量,b但实际上可能比直接编写循环要慢一些。如果你有大量的游戏对象(数千个或更多),你会想优化你的存储结构,使其优于O(n)搜索。@EricJ.Yes-但如果不改变存储机制,循环使用此解决方案将不会给您带来太多好处。根据使用方式和时间,更改为字典或按类型划分的集合等可能是一种优化。同意,但我已经看到了表明Linq to对象可以是si的基准测试在适当的情况下,比直接迭代要慢很多(百分比方面,绝对数方面没有那么多)。仅供参考-我的解决方案也不会(必然)迭代整个数组,但在找到第一个数组时,由于Any()嗯,我不知道。谢谢Reed。这是因为LINQ的延迟执行模型。据我所知(我可能离这里很远)is关键字处理父反射,如果我决定将来委托mario,我可能不想与这个类交互,那么它也会创建与它们的交互,因为它们继承自基类mario,因为“is”适用于反射。@MatthewCrandall:is运算符。@MatthewCrandall好吧,你是对的,它还包括继承类型-但我不清楚这是一个不必要的影响。无论如何,我已经更新了我的帖子。另外,我相信你错误地将继承称为反射。@MatthewCrandall:只是出于好奇,你为什么要这么做你继承自
Mario
,而它不是Mario,应该被区别对待?这种对继承的解释很奇怪。@TimSchmelter也许我们不清楚,或者也许我只是还不了解继承。Mario是一个类,它控制玩家控制的对象。如果将来,我决定加电(如蘑菇、火花、锤子等),我可能会选择以它为基础制作课程,只需编辑课程的行为即可实现通电后的能力。此外,请记住,我是计算机编程的第一年,因此我可能会误解课堂上尚未正式“教授”的结构和主题。
    Array a = new object[] { "The meaning of life.", 42 };
    bool hasString = a.ContainsType(typeof(string)); // true
    bool hasInteger = a.ContainsType(typeof(int));  // true
    bool hasChar = a.ContainsType(typeof(char));  // false