Miguel Moura
Miguel Moura

Reputation: 39364

Class inherting a list of objects

I have the following methods:

void Add<T>(T entity) where T : class;
void Add<T>(IEnumerable<T> entities) where T : class;

And I have the following class:

public class MimeTable : List<Mime> { }

Then I tried to use it as follows:

Add(new MimeTable())

I get an error because it is called the first Add method and not the second.

Should be called the second one since MimeTable is a List?

Is there a way to solve this?

Upvotes: 0

Views: 82

Answers (3)

Nicholas Carey
Nicholas Carey

Reputation: 74177

You can also cast your MimeTable to IEnumerable<Mime> and the second overload will be invoked. This code:

class Mime
{
}

class MimeTable : List<Mime>
{
}

class Widget
{
    public void Add<T>( T entity ) where T:class
    {
        Console.WriteLine("Add/1 overload #1" ) ;
    }
    public void Add<T>( IEnumerable<T> entity ) where T:class
    {
        Console.WriteLine( "Add/2 overload #2" ) ;
    }
}

class Program
{

    static int Main( string[] args )
    {
        MimeTable mt = new MimeTable() ;
        Widget    widget = new Widget() ;

        widget.Add( mt ) ;
        widget.Add( (IEnumerable<Mime>) mt ) ;

        return 0 ;
    }

}   // program

produces this output:

Add/1 overload #1
Add/2 overload #2

But as noted, why not just rename the method to make the intention clear?

Upvotes: 0

Arin Taylor
Arin Taylor

Reputation: 390

Like others have said, you probably want to rename the second Add method to AddRange or something of your liking. If for some reason you really want to achieve alternate functionality when you pass a List, you can rename the second Add method and add a check at the beginning of the first Add method that says something like:

if (entity is IList)
{
    AddRange(entity);
    return;
}

Upvotes: 0

Servy
Servy

Reputation: 203802

In this situation the second Add overload is just about impossible to actually be invoked. The only ways you're going to have to invoke it are through the use of reflection, or using named arguments (since the parameter names differ), neither of which is particularly practical.

This is due to the betterness algorithm for overload resolution. An overload is "better" than another if it doesn't require an implicit conversion and another one does. Your first overload, once the generic argument is inferred, is accepting an argument of type MimeTable, which is the exact type of the parameter. The second overload is accepting an IEnumerable<Mime> which requires an implicit conversion. That overload is going to be "worse". There will never be a situation where that overload would ever be "better".

The most convenient option is almost certainly going to be using two different methods here, rather than overloading a single method. Any other means of distinguishing them that you have would be more work than typing a different name.

Upvotes: 3

Related Questions