Similar threads that addresses this are possibly there on SO, but I do not understand them 🙁
I have a scenario like this:
internal static void AddToListBox(ListBox lb, User usr)
{
if (CanAddUser(lb, usr))
lb.Items.Add(usr);
}
static bool CanAddUser(ListBox lb, User usr)
{
foreach (User u in lb.Items)
{
if (u.Id == usr.Id)
return false;
}
return true;
}
Now I have another exactly similar scenario like this:
internal static void AddToList(List<User> lstUser, User usr)
{
if (CanAddUser(lstUser, usr))
lstUser.Add(usr);
}
static bool CanAddUser(List<User> lstUser, User usr)
{
foreach (User u in lstUser)
{
if (u.Id == usr.Id)
return false;
}
return true;
}
Basically both set does the same thing. I was curious if I could make it one function, but this is only how it worked, which makes the code more verbose:
internal static void AddToList(IEnumerable enumerable, User usr)
{
if (enumerable is ListBox.ObjectCollection)
{
if (CanAddUser(enumerable, usr))
((ListBox.ObjectCollection)enumerable).Add(usr);
}
else if (enumerable is List<User>)
{
if (CanAddUser(enumerable, usr))
((List<User>)enumerable).Add(usr);
}
}
internal static bool CanAddUser(IEnumerable enumerable, User usr)
{
foreach (User u in enumerable)
{
if (u.Id == usr.Id)
return false;
}
return true;
}
As I said it works, but the if else block makes it look ugly and kills the idea of shortening the code. Could I be doing something like this:
internal static void AddToList(IEnumerable enumerable, User usr)
{
if (CanAddUser(enumerable, usr))
((whatever the type is passed, just find it yourself)enumerable).Add(usr);
}
??
I tried
internal static void AddToList(IEnumerable enumerable, User usr)
{
if (CanAddUser(enumerable, usr))
((enumerable.GetType()) / (typeof(enumerable))enumerable).Add(usr);
//both which wont compile.
}
So how to go about this? Is it impossible to cast IEnumerable to an unknown type? Or would the solution be just too messy that I should drop the plan? Anything can be done if I know the passed IEnumerable will be only of type ListBox.ObjectCollection and List<User> other than the if else logic? Sorry for the lengthy piece, just needed to explain my requirement..
UPDATE: StriplingWarrior’s answer necessarily solves my problem, but I wonder how would be the object cast to its original type, if I’m to implement the last function. Possibly via Reflection or something. I will mark the solution to this as answer. Thanks @StriplingWarrior once again.
UPDATE 2:
To make it more clear, forget all what has been posted above. Suppose I have a function like below. Admonish() is an extension method I have defined on objects of type List<Naughty> and List<Obedient> separately. How will I be able to write just one Sanitize function and pass either List<Naughty or List<Obedient to it? Like this:
internal static void Sanitize(IEnumerable enumerable)
{
enumerable.Admonish();
}
??
I know I can do this:
internal static void Sanitize(IEnumerable enumerable)
{
if (enumarable is List<Naughty>)
((List<Naughty>)enumerable).Admonish();
if (enumarable is List<Obedient>)
((List<Obedient>)enumerable).Admonish();
}
How will I be able to do it in one go, like this:
internal static void Sanitize(IEnumerable enumerable)
{
((Determine type here, but how??)enumerable).Admonish();
}
Hope question is clear. I’m not looking for a special case solution but a general solution to get the type at run time so that an object can be cast to its type !!
Since
ListBox.ObjectCollectionimplements theIListinterface, you should be able to use that interface for both cases.The only reason this didn’t work for
IEnumerableis because that interface doesn’t have anAddmethod.Response to Update 2
This question is a lot more complicated than it appears at first glance, and the answer would depend on what your Admonish method does. Does it just iterate the list and perform something specific on each member of the list?
If this is the case, you can just make both Naughty and Obedient implement a specific interface:
On the other hand, if Admonish does something different depending on what type you’re looking at, that’s not so simple:
In this case, the only way to automatically call the correct Admonish method is to use reflection to find and call it. As far as the .NET framework is concerned, there is no reason to believe that the two
Admonishmethods are in any way related, so you can’t just pretend that they’re the same method.If you’re willing make Admonish a non-static method, you might use the
dynamickeyword to accomplish more or less what you’re trying to do, but it won’t work on extension methods:But even this approach only works if the enumerable you pass in is backed by a generic
IEnumerable<Naughty>orIEnumerable<Obedient>. If you pass it aListBox.ObjectCollection, even the dynamic runtime framework won’t be able to figure out which Admonish method to call.Finding and calling the correct method via reflection
Let me begin by saying reflection is usually not the best solution for problems like this. Reflection is slow, and it negates most of the advantages of compiled programming languages. But if you think that’s the way to go, here’s how you’d do it. Supposing your
Admonishmethod signatures look like this:… and assuming you have a list whose actual implementation type implements
IEnumerable<Naughty>:… you could find and call the method like this: