问题
I have a method, accepting a Hashtable (yes I know, it's outdated..) as argument:
public static LuaTable HashtableToLuatable(Hashtable t, int depth = 1)
This works correctly.
Now I'd like to accept an ArrayList as first parameter as well, so you can let 't' have the value of both a Hashtable and an ArrayList. Currently I have copy-pasted the method two times, like this:
public static LuaTable ArraylistToLuatable(ArrayList t, int depth = 1)
The rest is exactly the same.
I think there's a way to merge this.
回答1:
Both classes implement the ICollection interface, so if your 'common code' will work against the definition of the ICollection interface, you could use that for your parameter type.
回答2:
Both types implement IEnumerable
and ICollection
, so rewrite your method signature to use one of those instead:
public static LuaTable EnumerableToLuaTable(IEnumerable t, int depth = 1)
or
public static LuaTable CollectionToLuaTable(ICollection t, int depth = 1)
I'd prefer the IEnumerable
option over ICollection
, if you don't need anything in ICollection
.
回答3:
You have shown an example of method overloading, and so far what you are doing works within the framework of C#.
The question is, what what must the method do with the passed-in value. There must be some means of treating them as "equivalent". One way to do that is if both types implement the same interface.
ArrayList implements: IList, ICollection, IEnumerable
Hashtable implements: IDictionary, ICollection, IEnumerable
If the code inside your method body just treats the first argument like a collection, you can change the method signature to:
public static LuaTable HashtableToLuatable(ICollection t, int depth = 1)
If your implementation does not use or require everything in ICollection, you could instead specify
public static LuaTable HashtableToLuatable(IEnumerable t, int depth = 1)
More objects implement IEnumerable than ICollection, so using IEnumerable (if possible) will allow for greater flexibility down the road to pass in a different type of object.
回答4:
Both of these (terribly outdated) types implement two common interfaces, namely; IEnumerable
and ICollection
. So, you can set a generic constraint based on on of those interfaces.
static void ArraylistToLuatable<T>( T collection ) where T : IEnumerable
{
foreach( var item in collection )
{
// do something
}
}
Of course, this still sucks, because item
is going to be of type object
, which will work better for your ArrayList
argument than your HashTable
argument as, under the covers, you have to deal with a DictionaryEntry
somehow, which means you have to check its type in the method and cast your item
appropriately.
Are you sure you can't use a more up to date generic collection type? Would it be possible to wrap them in a generic collection as you get them from your DLL? I suppose it depends on how much of this sort of thing is needed on your end. If it's just one or two methods it's probably fine this way.
回答5:
You could try generics, if that works for you..
public static LuaTable <T> HashtableToLuatable(T t, int depth = 1) where T : ICollection
You may also derive your own datatypes if the above does not fit your case..
来源:https://stackoverflow.com/questions/10128823/how-to-let-a-method-accept-two-types-of-data-as-argument