2

I am trying to create a "Mario" video game, and in order to obtain intersecting objects, our teacher provided us with an example demonstration, which allows the object to detect if it is touching EXACTLY one other object, and the first object that the method finds, is returned. I am trying, instead to return an array of every object that the current object is currently touching. I was capable of returning an array of every object currently touching it, but now I need an easy/efficient way to check if the array contains an object of a required type, such as

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

The array that is being checked if it Contains(Mario), is the returned array of the intersecting Sprites, but when I ask if it actually contains objects of type Mario, it says "Error 14 'WindowsGame10.Mario' is a 'type' but is used like a 'variable' ". I Know I could do this with a for loop, and ask each individual index within the array if (array[i].GetType() == typeof(Mario)), but for the amount of times I would need to perform this check within the code, and retype the same code over and over again, I feel that I need to learn a more efficient way to perform this. I am in my first year of Computer Programming, and I am working with C# XNA, and I need to have some solution that I can understand. If there is a better way to do this, please let me know.

5 Answers5

6

You can use LINQ's OfType() and Any() methods:

if (array.OfType<Mario>().Any())
{
Reed Copsey
  • 554,122
  • 78
  • 1,158
  • 1,373
  • Thanks. That just greatly reduced the amount of for loops I was in danger of using. – Matthew K. Crandall Mar 10 '12 at 00:21
  • 3
    Note that you are still traversing the array until you find a first match, or traversing the entire array if there is no match. Linq is a nice abstraction that reduces programming effort, but it's actually possible to be very marginally slower than coding the loop directly. If you have a large number of game objects (thousands or more), you would want to optimize your storage structure to get better than O(n) searches. – Eric J. Mar 10 '12 at 00:23
  • @EricJ. Yes - but without changing the storage mechanism, looping over this solution won't get you much. Changing to a dictionary or separate collections by type, etc, would potentially be an optimization, depending on how and when this is going to be used. – Reed Copsey Mar 10 '12 at 00:25
  • Agreed, though I have seen benchmarks that indicate that Linq to Object can be significantly (percentage wise, not so much in terms of absolute numbers) slower than directly iterating, under the right circumstances. – Eric J. Mar 11 '12 at 02:41
4

Using Linq you can do:

var marios = array.OfType<Mario>();
if (marios.Any())
{
     //Stuff
}
DaveShaw
  • 52,123
  • 16
  • 112
  • 141
2

if you just need to know if there is any Mario then

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

this will break out of the iteration as soon it finds the first match.

labroo
  • 2,901
  • 3
  • 27
  • 36
2

The Linq answers are great. Just to provide an alternative approach, you could define an extension method like this:

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

that would be used like this:

    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
Eric J.
  • 147,927
  • 63
  • 340
  • 553
1

Most straight forward way (without using LINQ) would be to use the is keyword:

foreach (Object obj in array)
{
    if (obj is Mario)
    {
        ...
    }
}

Update: If you need an exact Type match, and want to avoid code duplication, I think a rather simplistic extension method similar to this would be best -

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

And the use -

if (array.ContainsType(typeof(Mario)))
Acidic
  • 6,154
  • 12
  • 46
  • 80
  • To my understanding (and I could be way off here) the is Keyword deals with parent reflection, and if I decide to make delegates of mario in the future, that I may want unable to interact with this class, then It would also create an interaction with them, because they inherit from Base Class Mario, because "is" works with reflection. – Matthew K. Crandall Mar 10 '12 at 00:26
  • @MatthewCrandall: The is-operator [does not use Reflection and is very efficient](http://stackoverflow.com/a/1134104/284240). – Tim Schmelter Mar 10 '12 at 00:43
  • @MatthewCrandall Well, you are right that it also includes inheriting types - but it was unclear to me that that was an unwanted effect. Anyway, I've updated my post. Also, I believe you are wrongly referring to inheritance as reflection. – Acidic Mar 10 '12 at 00:47
  • 1
    @MatthewCrandall: Just out of curiosity, why would you inherit from `Mario`when it's **not** such a thing as Mario and should be treated differently? This interpretation of inheritance is odd. – Tim Schmelter Mar 10 '12 at 00:54
  • @TimSchmelter Maybe we were unclear, or Maybe I just don't yet understand inheritance. Mario is a class, which controls the object the player controls. If in the future, I decide to make powerups (For instance, Mushroom, fire flower, hammer, etc...), I may Choose to make classes that build off of it, and just edit the behaviors of the class to perform the abilities from the power-up. Also, keep in mind I am in my first year of computer programming, so I am kind of expected to misunderstand constructs and topics I have not yet been formally "taught" in class. – Matthew K. Crandall Mar 10 '12 at 01:08
  • @MatthewCrandall The last thing I want to do is sound patronizing, but you won't get far if you treat flaws as something "expected". – Acidic Mar 10 '12 at 01:18
  • I expect flaws, however, I also expect to discover them, and rectify them. I am beginning, so mistakes are expected. I want to learn, so I expect to learn from my mistakes, and fix them. No worries. The difference, is that I don't give up; I try to do better. – Matthew K. Crandall Mar 10 '12 at 01:21