I have a class
called Block that has a Draw
method. I want to make a function that draws a group of blocks
all at once. Since some groups are Arrays
and some are lists
, I had to add an overload that basically does the same thing as the base function but just takes in a different type of parameter. Any ideas on how to improve this code?
public static void DrawAll(Block[] arr) {
foreach(Block b in arr)
b.Draw();
}
public static void DrawAll(List<Block> arr) {
foreach(Block b in arr)
b.Draw();
}
I tried looking into Generics
but I can't iterate through T
because the compiler doesn't know it's a collection of blocks
.
// Doesn't work
public static void DrawAll<T>(T arr) {
foreach(var b in arr)
b.Draw();
}
Using the is
keyword and casting
also doesn't work because, from what I understand, you can't make two different casts
in the same if
statement. So I'll have to separate the casts
and that just makes the code look even worse:
// Even dummer than just doing the overload
public static void DrawAll<T>(T arr) {
if (arr is Block[] blocksA)
foreach(Block b in blocksA)
b.Draw();
else if (arr is List<Block> blocksL)
foreach(Block b in blocksL)
b.Draw();
else throw new Exception("not a collection of blocks");
}
What you need is a useful common base type of List<T>
and T[]
or an interface implemented by both of them.
If you don't need the index (e.g. because you are using foreach
), then IEnumerable<Block>
will work for all kinds of collections and also (unrealized) results of LINQ expressions, e.g.: blocks.Where(b => b.Name.StartsWith("A"))
.
public static void DrawAll(IEnumerable<Block> blocks) {
foreach(Block b in blocks)
b.Draw();
}
If you need the index (e.g. because you are using for
), then IList<Block>
will accept List<Block>
as well as Block[]
.
// E.g. drawing blocks in reverse order
public static void DrawAll(IList<Block> blocks) {
for (int i = blocks.Count - 1; i >= 0; i--)
blocks[i].Draw();
}