0

I have an abstract class with a parameterfull constructor:

public abstract class LoggerAdapterBase<TLogger>
{
    protected readonly TLogger _logger;

    public LoggerAdapterBase(TLogger logger){
        this._logger = logger;
    }
}

In other class I have to create concrete class that implements abstract, but have a problem:

public class LoggerManager<TLogger, TLoggerAdapter>: ILoggerManager<TLogger> where TLoggerAdapter: LoggerAdapterBase<TLogger>
{
    private readonly TLogger _logger;
    public LoggerManager(TLogger logger)
    {
        this._logger = logger;
    }
    public LoggerAdapterBase<TLogger> CreateLogger(Configuration configuration)
    {
        return new TLoggerAdapter(this._logger);
        //Line above says: Cannot create an instance of the variable type 'TLoggerAdapter' because it does not have the new() constraint
    }
}

I don't know why compiler requires new() constraint because LoggerAdapterBase has a constructor that I use, and I've specified this to constraints, it should see the constructor as well as other methods from LoggerAdapterBase. What's wrong here?

Edit

Thank you for answer, I've solved it. I just made interface instead of abstract class and defined prop Logger. And added constraint new(). Now creating looks so:

return new TLoggerAdapter() { Logger = _logger };

It isn't an ideal implementation because of possible NullReferenceExceptions when create an instance out of the LoggerManager, and unexpected replacing of prop Logger.

Andr1o
  • 11
  • 3
  • C# Classes don't inherit constructors from their base class. The child class can invoke the parent class' constructor from its own constructor, but the parent class' constructor cannot be used to create an instance of the child class. – JLRishe Sep 24 '20 at 13:07

1 Answers1

0

Basically, you can't do what you want. Here's an example of why:

// This is perfectly valid
public class StringLoggerAdapter : LoggerAdapterBase<string>
{
    private StringLoggerAdapter() : base("anything")
    {
    }
}

What would you expect LoggerManager<string, StringLoggerAdapter>.CreateLogger to do? It doesn't have an accessible constructor to call, and the one constructor that is present doesn't have the parameter list that LoggerManager expects.

Constructors aren't inherited - just because the base class has a constructor with a particular parameter list doesn't mean that derived classes do.

Currently there's no way of requiring that a type argument has a particular parameter list - other than the new() constraint that requires a parameterless constructor.

There have been suggestions that the C# team might introduce this in a later version of C#, but it isn't present now and I don't expect it to be in C# 9.

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194