Search code examples
c#inheritanceoverriding

Virtual void not being overridden with override keyword in C#


I am trying to make a class the user of my library can derive from and then access a method for debugging the times of each action. Because my main debug method, where most information is stored, is static (and needs to be), I cannot use it to derive a class or add an overridable method in it. To combat this, I added the following code:

public static class Debug
{
    internal static void CallObjectEvent(string log)
    {
        new Call().CallEvent(new Log(log, Timer.GetTime()));
    }
}

internal class Call : IDebug
{
    internal void CallEvent(Log log)
    {
        base.Event(log);
    }
}

public class IDebug
{
    public virtual void Event(Log log) {Console.WriteLine("test");}
}

class Program : IDebug
{
    public override void Event(Log log)
    {
        Console.WriteLine(log.log);
    }
}

Every time, it outputs 'test' instead of the log message. How can I fix this? Are there any alternatives to do the same thing?


Solution

  • Your Debug.CallObjectEvent() method explicitly instantiates a Call object and calls the overridden method in that class:

    public static class Debug
    {
        internal static void CallObjectEvent(string log)
        {
            new Call().CallEvent(new Log(log, Timer.GetTime()));
        }
    }
    

    The CallEvent() method in the Call class simply calls base.Event(), which resolves to IDebug.Event(). The Program.Event() override is never invoked because Program is not in the class hierarchy at the point of the call.

    When you override a method or property, the override applies only to the class where it is defined (and all of its child classes, of course). Since Program isn't a parent class of Call there's no reason why its overrides would ever be referenced.

    From what you've written it looks like you're trying to set up a system for handling different log outputs depending on the program's requirements. You need a way to register the appropriate log writer for your program. Something like:

    public interface ILogWriter
    {
        void Event(Log item);
    }
    
    private class DefaultLogWriter : ILogWriter
    {
        public void Event(Log item)
        {
            Console.WriteLine($"[test] {item.Time} {item.Message}");
        }
    }
    
    internal static class Debug
    {
        private static ILogWriter _writer = null;
    
        public static ILogWriter Writer 
        { 
            get
            {
                if (_writer == null)
                    _writer = new DefaultLogWriter();
                return _writer;
            }
            set => _writer = value;
        }
    
        internal static void CallObjectEvent(string log)
        {
            Writer.Event(new Log(log, Timer.GetTime()));
        }
    }
    
    class Program
    {
        private class MyLogWriter : ILogWriter
        {
            public void Event(Log item)
            {
                Console.WriteLine($"[MyLogWriter] {item.Time} {item.Message}");
            }
        }
    
        static void Main()
        {
            Debug.Writer = new MyLogWriter();
    
            Debug.CallObjectEvent("Test message.");
        }       
    }