Re: Why can't I overload a generic method based on class/struct?

Tech-Archive recommends: Fix windows errors by optimizing your registry



On Feb 22, 8:41 am, "Marc Gravell" <marc.grav...@xxxxxxxxx> wrote:
In short, you simply can't... the language spec doesn't permit overloads
separated purely by constraints.

But you can just use null! The following does exactly what you want...

            int? a = null;
            string b = null;
            if (a != null) {...}
            if (b != null) {...}

In the case of generics, default(T) would also return either a null (class),
an empty-nullable (nullable-T) or a zero-value (struct).

Note that there appear to be some minor JIT optimisation issues with
unconstrained generic use of null tests, but even so, within a generic with
"T foo", testing foo against null will do the right thing for all 3 cases.

For some specific cases (benchmarked etc), I do have a suitable IsNull
method tucked away... but I honestly don't think you need it! If you let me
know more about what you are trying to do (and whay is/isn't working) I can
show you how it works... but I don't want to post it without reason, as it
might add more confusion than necessary...

Marc

Well, in my scenario, I am implementing a method similar to Left Outer
Join. I want all the elements from the outer list, even if there is
not a matching inner list element. I can easily make one of the types
Nullable, but then the rest of the arguments become more difficult.
For instance, I can't pass in Comparer<int>.Default.Compare anymore
because one of the arguments is Nullable. So I have to write method
like this:

delegate(int lhs, int? rhs)
{
return lhs < rhs ? -1 : rhs < lhs ? 1 : 0;
}

and instead of passing in two int[] I have to pass in an int?[] which
is just cumbersome.

That is why I was hoping for the overloading. There is no point in
making a generic method if it is so complicated to get the syntax
right that it ends up being longer than writing the method over again.
Here is my example method:

/// <summary>
/// Performs a left outer join on ranges sorted by the key
value.
/// </summary>
/// <remarks>The collections must be sorted by key.</remarks>
public static IEnumerable<KeyValuePair<TFirst, TSecond>>
LeftOuterJoin<TFirst, TSecond>(IList<TFirst> lhs,
IList<TSecond> rhs,
Comparison<TFirst, TSecond> keyComparison)
{
Debug.ArgumentNull(lhs, "lhs");
Debug.ArgumentNull(rhs, "rhs");
Debug.ArgumentNull(keyComparison, "keyComparison");
int lhsFirst = 0;
int rhsFirst = 0;
int position = rhsFirst;
bool found = false;
while (lhsFirst != lhs.Count)
{
int result = keyComparison(lhs[lhsFirst],
rhs[position]);
if (result < 0)
{
if (!found)
{
yield return new KeyValuePair<TFirst,
TSecond>(lhs[lhsFirst], default(TSecond));
}
else
{
found = false;
}
++lhsFirst;
position = rhsFirst;
}
else if (result > 0)
{
++position;
rhsFirst = position;
}
else
{
yield return new KeyValuePair<TFirst,
TSecond>(lhs[lhsFirst], rhs[position]);
++position;
found = true;
}
if (position == rhsCount)
{
position = rhsFirst;
if (!found)
{
yield return new KeyValuePair<TFirst,
TSecond>(lhs[lhsFirst], default(TSecond));
}
else
{
found = false;
}
++lhsFirst;
}
}
}

To call this with char, char? looks like this:

char[] lhs = new char[] { 'A', 'B', 'E', 'F' };
char?[] rhs = new char?[] { 'A', 'A', 'B', 'C', 'D',
'F' };
IEnumerable<KeyValuePair<char, char?>> pairs
= Algorithms.LeftOuterJoin<char, char?>(lhs, rhs,
delegate(char l, char? r)
{
return l < r ? -1 : r < l ? 1 : 0;
});
List<KeyValuePair<char, char?>> result = new
List<KeyValuePair<char, char?>>(pairs);

It's very uncomfortable.
.



Relevant Pages

  • Re: Creating IndexOf in a custom collection
    ... I started out with a custom collection by extending ... based on specific properties of the contained class, my Generics based ... Dale Preston ... public int FindIndex ...
    (microsoft.public.dotnet.languages.csharp)
  • Re: speed of generic code in Ada (vs Java)
    ... Is the situation similar with generics in Ada, GNAT, ... autoboxing that slows things down - java has both an int as a primitve ... which is a bit like comparing Ada arrays with Ada Containers. ...
    (comp.lang.ada)
  • Re: .NET generics & the .NET framework: not generic enough?
    ... I do wish there was a way to express that you want int, ... What if I create a BetterInt32? ... Generics are not CLS compatible, however you are free to use generics ... One of the reasons for struct & overloaded operators is to enable us as ...
    (microsoft.public.dotnet.languages.csharp)
  • Re: .NET generics & the .NET framework: not generic enough?
    ... >> primatives alone. ... >> int, ... > Generics are not CLS compatible, however you are free to use generics ...
    (microsoft.public.dotnet.languages.csharp)