xslipstream xslipstream - 18 days ago 8
C# Question

c#: inheritance and abstract classes - base. vs :base (in constructor initializers)

I'm getting an error: "The type Book' does not contain a constructor that takes 0' arguments" when I try to set my constructor as follows:

using System;
using System.Collections.Generic;
using System.IO;
abstract class Book
{

protected String title;
protected String author;

public Book(String t,String a){
title=t;
author=a;
}
public abstract void display();

}

class MyBook : Book
{
private int price = 0;

public MyBook(string t, string a, int p)
{
base.title = t;
base.author = a;
this.price = p;
}

public override void display()
{
Console.WriteLine($"Title: {title}");
Console.WriteLine($"Author: {author}");
Console.WriteLine($"Price: {price}");
}
}


I've narrowed down the issue to how I am using the base keyword. I should be using use a base constructor initializer, with the base keyword, in its constructor declaration.

public MyBook(string t, string a, int p)
: base(t, a)
{
this.price = p;
}


Will someone please explain to me why I cannot use base. in my constructor here? Is it because title and author variables are both protected members of the abstract class? I thought that since I'm deriving from Book, I have access to these protected members. Or is it because I haven't instantiated my subclass and thus I cannot set my constructor this way?

Answer

You CAN use protected properties in the way you were trying to. That's not the problem you're encountering. When you try to create an instance of the derived class, the program needs to know which constructor of the base class to call to create that portion of the object. If you don't specify, the default (no argument) constructor is called. The base class doesn't have one of those, so you get the error. :base(t,a) is necessary to tell it WHICH constructor to use, and what arguments to pass it. If you wanted, you could do:

public MyBook(string t, string a, int p)
: base(t, a) 
{
        base.title = t;
        base.author = a;
        this.price = p;
}

Of course, in this example that would be silly, but you can see that it will let you use those properties in the way you were trying.