Generic parameters without constraints are used as if they were of type System.Object
, that's why the compiler argues about using a.Length
.
To get type specific syntax available on a generic parameter type you need to add constraints, e.g.:
public void Count<T>(T list) where T : IList
String
and byte[]
have only two seemingly common interfaces, IEnumerable
and IEnumerable<T>
, so it is the only usable thing here. However, string
is IEnumerable<char>
and byte[]
is IEnumerable<byte>
, so we need to fallback to IEnumerable
:
public int MemCmp<TEn>(TEn obj1, TEn obj2) where TEn : IEnumerable
{
IEnumerator enumerator1 = obj1.GetEnumerator();
IEnumerator enumerator2 = obj2.GetEnumerator();
bool has1Next;
bool has2Next;
do
{
has1Next = enumerator1.MoveNext();
has2Next = enumerator2.MoveNext();
if(has1Next && has2Next)
{
if (enumerator1.Current is IComparable)
{
int comparison = ((IComparable) enumerator1.Current).CompareTo(enumerator2.Current);
if (comparison != 0) return (comparison > 0) ? 1 : -1;
}
else if (enumerator2.Current is IComparable)
{
int comparison = ((IComparable) enumerator2.Current).CompareTo(enumerator1.Current);
if (comparison != 0) return (comparison > 0) ? -1 : 1;
}
else
{
throw new ArgumentException("Not comparable types");
}
}
else
{
if(has1Next)
{
return 1;
}
else
{
return -1;
}
}
} while (true);
}
Usage:
MemCmp<IEnumerable>(a, b);
This is one possible solution to implementing your method.
But, due to inherent type incomatibility here, and the static compilation of generics, we have lost strong typing. So, the answer to the question is yes, but at a considerable cost. Even chars and bytes will get boxed when cast to IComparable
.
Note also that in your code
if ( a[i] != b[i] ) ...
works because of built-in implicit conversions between byte
and char
, which cannot be mimicked with generics.