Search code examples
c#abstract-class

How to use abstract class as variable type in C#


I'm trying to use an abstract class as variable type in C# and getting System.StackOverflowException: 'Exception_WasThrown' error when try to read ResultData.ValuesDescription

public abstract class Plugin
{
    public abstract string Name { get; }
    public abstract string Description { get; }
    public abstract Results ResultData { get; }
    public abstract bool Init(string Symbol);
}
public abstract class Results
{
    public abstract bool Values { get; set; }
    public abstract string ValuesDescription { get; set; }
}

public class Test : Plugin
{
    public override string Name { get => "Lortem Ipsum Moving Average"; }
    public override string Description { get => "Lorem Ipsum dolor sit amet, consectetur adipiscing elit."; }
    public override Results ResultData {
        get {
            ResultData.Values = true;
            ResultData.ValuesDescription = "Lorem Ipsum result in numeric format";
            return ResultData;
        }
    }
    public override bool Init(string Symbol)
    {
        return true;
    }
}

Any suggestion on what's going on?


Solution

  • The answer from @ipodtouch0218 covers the immediate issue of the stack overflow error from the ResultData getter calling itself, but the core underlying issue is that you currently have a Result class that is marked as abstract with no concrete implementation. You cannot use an abstract class that doesn't have an implementation somewhere.

    From what it sounds like, you want implementations of Plugin to have read-only descriptor metadata associated with them. You can do this with an abstract Results class, but you will need to create subclasses that implement its getters. For instance:

    public abstract class Results
    {
        // Mark these with only getters because setters don't make
        // sense if they are intended to be read only.
        public abstract bool Values { get; }
        public abstract string ValuesDescription { get; }
    }
    
    public class TestResults : Results
    {
        // Create a static instance so you don't need to instantiate
        // over and over again.
        public static readonly TestResults instance = new TestResults();
    
        // Provide a concrete implementation for these properties
        public override bool Values { 
            get { return true;  } 
        }
        public override String ValuesDescription { 
            get { return "Lorem Ipsum result in numeric format"; } 
        }
    }
    
    public abstract class Plugin
    {
        // ...
        public abstract Results ResultData { get; }
        // ...
    }
    
    public class Test : Plugin
    {
        // ...
        public override Results ResultData 
        {
            // Return the static instance
            get { return TestResults.instance; }
        }
        // ...
    }
    

    As for whether this is a good approach to accomplish this, it's certainly a bloated solution. For one thing, it would make more sense to implement this with interfaces rather than abstract classes, or alternatively using some kind of factory pattern. And for another, seeing as the Results class is meant to only contain static information that will never change, it begs the question as to why it needs to be its own class at all and why its properties can't simply be part of the Plugin/Test classes, or at the very least converted into a simple struct or record.