29

I have these 2 classes that are respectively called: Malicious and MaliciousSmall:

Code of Malicious:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace DataModel.MaliciousCode
{
    public class Malicious : MaliciousSmall
    {
    }
}

Code of MaliciousSmall:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Diagnostics;
using System.Data;
namespace DataModel.MaliciousCode
{
    public class MaliciousSmall
    {
        public int Id { get; set; }
        public int MaliciousCodeAlertId { get; set; }
        public string SourceId { get; set; }
        public int MalCodeID { get; set; }
        ......................................................
        ......................................................
        ......................................................

        // CONSTRUCTOR:

       public MaliciousSmall(DataRow row)
        {
            Id = int.Parse(row["Id"].ToString());

            MaliciousCodeAlertId = (row["MaliciousCodeAlertId"] is DBNull) ? MaliciousCodeAlertId = -1 : MaliciousCodeAlertId = int.Parse(row["MaliciousCodeAlertId"].ToString());
            SourceId = (row["SourceId"] is DBNull) ? SourceId = "" : SourceId = row["MaliciousCodeAlertId"].ToString();
            MalCodeID = (row["MalCodeID"] is DBNull) ? MalCodeID = -1 : MalCodeID = int.Parse(row["MalCodeID"].ToString());
            Title = (row["Title"] is DBNull) ? Title = "" : Title = row["Title"].ToString();

        ......................................................
        ......................................................
        ......................................................
        }

}

My problem is that, after that I have implementet the MaliciousSmall class I obtain the following error on the Malicious constructor:

Error 53 'DataModel.MaliciousCode.MaliciousSmall' does not contain a constructor that takes 0 arguments C:\Develop\EarlyWarning\public\Implementazione\Ver2\DataModel\MaliciousCode\Malicious.cs 9 18 DataModel

What can I do to solve it?

I tried to create an empty constructor that take a DataRow object as paramether, something like it:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Diagnostics;
using System.Data;

namespace DataModel.MaliciousCode
{
    public class Malicious : MaliciousSmall
    {

        public Malicious(DataRow row)
        {

        }
    }
}

But I still have the same problem. What am I missing? What can I do to solve?

Ondrej Janacek
  • 12,486
  • 14
  • 59
  • 93
AndreaNobili
  • 40,955
  • 107
  • 324
  • 596
  • you need to add a constructor that takes no row: public Malicious() { } – Goran Štuc Mar 11 '14 at 09:23
  • 5
    @GoranŠtuc: No, that won't work. Look at the inheritance. – Jon Skeet Mar 11 '14 at 09:31
  • 2
    Actually, this questions have been answered many times here on SO: [here](http://stackoverflow.com/questions/7230544/c-sharp-error-parent-does-not-contain-a-constructor-that-takes-0-arguments), [here](http://stackoverflow.com/questions/12138221/does-not-contain-a-constructor-that-takes-0-arguments) and [here](http://stackoverflow.com/questions/15580168/c-sharp-inheritance-issue-does-not-contain-a-constructor-that-takes-0-argument). Next time, search first, please. – Ondrej Janacek Mar 12 '14 at 07:16

6 Answers6

84

The error is telling you that the Malicious constructor can't find a suitable constructor to chain to in its base class (MaliciousSmall).

The initial problem is that your derived class constructor implicitly contains this constructor:

public Malicious() : base()
{
}

Or even when you've added an explicit constructor, it's still trying to chain to a parameterless one:

public Malicious(DataRow row) : base()
{
}

... but there is no such parameterless constructor in the base class (MaliciousSmall), hence the error.

I think you want to chain to the constructor taking a row (the one you have declared in MaliciousSmall):

public Malicious(DataRow row) : base(row)
{
}

That's assuming you always want a row to be provided to the constructor. If you actually want to allow an instance to be created without specifying a row, then you need to add a parameterless constructor to the base class:

public MaliciousSmall()
{
    // Set fields/properties to some default values
}

You'd probably then want your derived class to have two constructors:

public Malicious() // Implicitly chain to the parameterless base constructor
{
}

public Malicious(DataRow row) : base(row) // Chain to parameterized constructor
{
}

See my article on constructor chaining for more details.

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • So what are you saying to me is that doing public Malicious(DataRow row) : base(row) I am executing the override of the MaliciousSmall constructor that in my Malicious constructor? – AndreaNobili Mar 11 '14 at 09:35
  • 9
    @AndreaNobili: Constructors aren't virtual - you don't *override* them. However, each constructor needs to *chain* to either another constructor in the same class, or a constructor in the base class - that chained constructor is executed before the body of the constructor which is doing the chaining. That code chains from the `Malicious(DataRow)` constructor to the `MaliciousSmall(DataRow)` constructor. Read the article I've linked to at the bottom of my answer. – Jon Skeet Mar 11 '14 at 09:36
  • 2
    @AndreaNobili , it's worthwhile to read Jon Skeets article on how constructors work if you are going to do C# programming. He mentioned it briefly below his answer: http://www.yoda.arachsys.com/csharp/constructors.html – John Korsnes Mar 11 '14 at 09:39
  • Ok, perfect, tnx so much, now I will also read your artigle – AndreaNobili Mar 11 '14 at 10:01
  • Holy cow, why so... strange, I would say, rules of constructor chaining? It looks like the whole problem is that .NET is too lazy to generate a default constructor! – hijarian Mar 12 '14 at 03:42
  • 8
    @hijarian Not at all. If you explicitly write a non-default constructor, generating a default constructor would be *exactly the wrong thing to do*. It would let any consumer of your class completely bypass the invariants you've attempted to put in place. – Chris Hayes Mar 12 '14 at 04:17
7

I tried to create an empty constructor that take a DataRow object as parameter

I think you have the term empty confused. An empty constructor accepts no parameters by definition. You cannot have an empty constructor with parameters.

If you'd like to keep the parameter in the derived class's constructor too, you need to use the base keyword to specify the base constructor.

public Malicious(DataRow row)
    : base(row)
{
}
Connell
  • 13,925
  • 11
  • 59
  • 92
4

You class Malicious has not defined any constructor at all, and from the MSDN docs for Using Constructors

Unless the class is static, classes without constructors are given a public default constructor by the C# compiler in order to enable class instantiation.

That means your class has:

public class Malicious : MaliciousSmall
{
   public Malicious()
   {
   }
}

From the same MSDN link

In a derived class, if a base-class constructor is not called explicitly by using the base keyword, the default constructor, if there is one, is called implicitly.

That effectively means:

   public Malicious() :base() //implicitly calling base class constructor

Since your base class doesn't have a default constructor (one with no parameter) you get the error.

Now you have two options to fix that error.

  1. Define a default constructor in your base class.
  2. Explicitly call the base constructor from your derived class.

Probably for your situation it seems better to call the base constructor explicitly, since both the constructors are receiving same type parameter. You can do:

public Malicious(DataRow row) :base(row)
Habib
  • 219,104
  • 29
  • 407
  • 436
3

If you don't want to add a parameterless constructor, pass the row to the base class constructor:

public Malicious(DataRow row):base(row)
{ 

}
Mihai Hantea
  • 1,741
  • 13
  • 16
2

If you are deriving any class from base class then you should either add parameterless constructor in base class or spefify a base class constructor to be called at derived class. So in order to solve your issue: Solution 1: Add parameterless constructor in base class i.e. at MaliciousSmall as,

public MaliciousSmall()
{
}

Solution 2: Specify base class constructor at derived class constructor as,

public DataRow row;
public Malicious: base(row)
{
}

Hope this will help you!

Pankaj
  • 234
  • 3
  • 14
0

If there are no constructors defined in the class the compiler provides a default/parameterless constructor which is used to instantiate its corresponding objects as shown below.

class MaliciousSmall
{
    //if no constructors are defined then compiler adds the following
    //public MaliciousSmall()
}

class Malicious: MaliciousSmall
{
    //if no constructors are defined then compiler adds the following
    //public Malicious() : base()
}

Malicious obj = new Malicious();

Since you have defined a constructor in the base class the compiler assumes that you do not require a default/parameterless constructor. When the default constructor of MaliciousSmall tries to call the default constructor of its base class the constructor chaining breaks.

class MaliciousSmall
{
    public MaliciousSmall(DataRow row)
    {
        //compiler will not supply a default constructor
    }
}

class Malicious: MaliciousSmall
{
    //if no constructors are defined then compiler adds the following
    //public Malicious() : base()
}

Malicious obj = new Malicious();

The instantiation of the object requires the default constructor of the Malicious class to be called which in turn tries to call the default constructor of the base class, but since this doesn't exist, the constructor chaining breaks.

It is advised that we use the required constructors such that it doesn't cause the chaining to break.

class MaliciousSmall
{
    public MaliciousSmall()
    {
        //
    }

    public MaliciousSmall(DataRow row)
    {
        //
    }
}

class Malicious:MaliciousSmall
{
    public Malicious()
    {
        //
    }

    public Malicious(DataRow row):base(row)
    {
        //
    }
}

Malicious obj = new Malicious();

Constructors are very important since, I don't think your program gets anywhere without an object instantiation, please do make sure to visit MSDN and do take an effort to read about this keyword.

Jerric Lyns John
  • 936
  • 10
  • 25