saastn
saastn

Reputation: 6025

Instantiating of a class derived from a generic one that has params in its constructor

I have this generic class Foo<> with two constructors. One of them accepts variable number of parameters using params keyword. The other nongeneric class Bar is derived from Foo<>. The problem is that Bar does not accept instantiating with constructor that hasparams.

This is a sample:

using System;

namespace ConsoleApp1
{
    class Foo<T> where T : IComparable<T>
    {
        private Foo() { }
        public Foo(params T[] list) : this() { }
    }
    class Bar : Foo<int> { }


    class Program
    {
        static void Main(string[] args)
        {
            Foo<int> foo = new Foo<int>(1, 2); // it compiles
            Bar bar = new Bar(1, 2); // but CS1729 here!
        }
    }
}

It gives a compiler error:

Error CS1729: 'Bar' does not contain a constructor that takes 2 arguments

What am I missing here?

Upvotes: 0

Views: 347

Answers (3)

canton7
canton7

Reputation: 42360

Constructors aren't inherited in C#. If you don't specify a constructor, the compiler will generate a parameterless constructor for you, which calls the base class's parameterless constructor. If your class derives from a base class which doesn't have any non-private parameterless constructors, the compiler errors.

So your plan of getting Bar to inherit the Foo constructor which takes a params T[] will never work.

It turns out that what's happening here is that the compiler has realised that it can generate a parameterless constructor which calls the base Foo(params T[]) constructor, by passing an empty array. See it here.

In your case, you need to give Bar its own constructor:

class Bar : Foo<int>
{
    public Bar(params int[] list) : base(list) { }
}

Upvotes: 2

Avner Shahar-Kashtan
Avner Shahar-Kashtan

Reputation: 14710

This has nothing to do with generics. It's just that constructors are not, by default, inherited in child classes. The fact that Foo<int> has a params int[] constructor doesn't automatically mean Bar has it too:

Not all members of a base class are inherited by derived classes. The following members are not inherited:

  • Instance constructors, which you call to create a new instance of the class. Each class must define its own constructors.

(from the C# Inheritance Tutorial on MS Docs)

You'll have to define a specific constructor for Bar and chain the base call to it:

 public Bar (params int[] list) : base(list) {}

Upvotes: 2

yv989c
yv989c

Reputation: 1553

You are missing implementing that constructor from Foo in Bar:

class Foo<T> where T : IComparable<T>
{
        private Foo() { }
        public Foo(params T[] list) : this() { }
}

class Bar : Foo<int>
{
    public Bar(params int[] list) : base(list) { }
}

Upvotes: 3

Related Questions