Home | Contact Us | FAQ | Search & Site Map | Link to Us
Sign In | Join | Other 45 Sites in Network
HomeAnnouncementsFree MagazinesWhite PapersSubmit Content
Discussion GroupsASP.NETWindows FormsLanguages.NET FrameworkVisual Studio.NET
Articles.NET FrameworkASP.NETToolsWindows Forms
.NET DirectoryOpen Source ProjectsUser GroupsWeb Resources
Related Topics
Visual Basic 6SQL ServerMS AccessOther DB ProductsMS Server ProductsMore Topics ...

.NET Forum / Languages / C# / February 2008

Tip: Looking for answers? Try searching our database.

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

Thread view: 
Enable EMail Alerts  Start New Thread
Thread rating: 
jehugaleahsa@gmail.com - 22 Feb 2008 15:31 GMT
Hello:

I was hoping to write a method that returned a T? for value types and
a T for reference types. I assumed that I could overload a generic
method based on the constraint of class or struct.

The intention was to return null for any type, using Nullable<T> for
value types and plain null for references.

Why can't the compiler distinquish?

Thanks,
Travis
Marc Gravell - 22 Feb 2008 15:41 GMT
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
jehugaleahsa@gmail.com - 22 Feb 2008 16:40 GMT
> In short, you simply can't... the language spec doesn't permit overloads
> separated purely by constraints.
[quoted text clipped - 20 lines]
>
> 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.
Rene - 22 Feb 2008 17:47 GMT
Assuming I understand your question correctly..

Regardless whether the return type is generic or not, the C# compiler will
not allow you to overload a method based on the return type of the method.
So for example, the following won't compile:

public Exception DoIt()
public EventArgs DoIt()

But you already knew that :)

> Why can't the compiler distinquish?

I believe this is a limitation on the C# compiler, if you where to write
your own IL then I think the runtime is capable of overloading method using
the return value as the method signature.

> Hello:
>
[quoted text clipped - 9 lines]
> Thanks,
> Travis
jehugaleahsa@gmail.com - 22 Feb 2008 20:45 GMT
> Assuming I understand your question correctly..
>
[quoted text clipped - 32 lines]
>
> - Show quoted text -

What about having different method names . . . is that a good idea? I
don't think it is. People using my code don't really want to have to
distinguish between one or the other. Sigh . . . I guess I will stick
to the ugly formatting.

Free Magazines

Get these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...

Oracle MagazineNetwork ComputingComputer WorldBio-IT WorldeWeekInformation WeekInfosecurity
 
Sign In
Join
My Latest Posts
My Monitored Threads
My Blog
My Photo Gallery
My Profile
My Homepage

Start New Thread
Enable EMail Alerts
Rate this Thread



©2008 Advenet LLC   Privacy Policy - Terms of Use
This website includes both content owned or controlled by Advenet as well as content owned or controlled by third parties.