Search code examples
c#abstract

nullable implemention of non-nullable methods of an abstract class


I have three classes. An interface called A, and B and C that implement A. Also B has an instance of C. Methods of A cannot be null. However, C may return null from time to time. Class B checks methods of the C instance and if the return value of C is null it will return self values(values from B).

public abstract class A
{
bool abstract method1();
bool abstract method2();
}

public class B:A
{
public C c;
override bool method1()
{
//if c.method1 is not null return c.method1() otherwise do some other functionality
}
}

public class C:A
{
?
}

I don't want to throw exceptions due to some performance concerns. How can I implement the C class since I can't change the type of the override class to nullable?


Solution

  • With the strict requirements as stated, I managed to come up with a kind of silly solution, but oh well - it's something..

    void Main()
    {
        var a = new AProxy(new C(), new B());
        for (int i = 0; i < 15; i++)
        {
            a.method1();
            a.method2();
        }
    }
    public abstract class A
    {
        public abstract bool method1();
        public abstract bool method2();
    }
    public class AProxy : A
    {
        readonly A primary;
        readonly A secondary;
        public AProxy(A primary, A secondary)
        {
            this.primary = primary;
            this.secondary = secondary; 
            if(primary is IReturnsNulls)
                ((IReturnsNulls)primary).LastResultNull += (s, e) =>
                    useSecondary = true;
        }
        private bool useSecondary;
        private bool UseSecondary
        {
            get 
            {
                if(useSecondary == true)
                {
                    useSecondary = false;
                    return true;
                }
                return useSecondary;
            }
        }
        public override bool method1()
        {
            var result = primary.method1();
            return UseSecondary ? secondary.method1() : result;
        }
        public override bool method2()
        {
            var result = primary.method2();
            return UseSecondary ? secondary.method2() : result;
        }
    }
    public class B : A
    {
        public override bool method1()
        {
            Console.WriteLine ("B, method1 (secondary)");
            return true;
        }
        public override bool method2()
        {
            Console.WriteLine ("B, method2 (secondary)");
            return true;
        }
    }
    public interface IReturnsNulls
    {
        event EventHandler LastResultNull;
    }
    public class C : A, IReturnsNulls
    {   
        static Random random = new Random();
        public override bool method1()
        {
            Console.WriteLine ("C, method1");
            var result = (random.Next(5) == 1) ? (bool?)null : true;
            if(result == null && LastResultNull != null)
                LastResultNull(this, EventArgs.Empty);
            return result ?? false;
        }
        public override bool method2()
        {
            Console.WriteLine ("C, method2");
            var result = (random.Next(5) == 1) ? (bool?)null : true;
            if(result == null && LastResultNull != null)
                LastResultNull(this, EventArgs.Empty);
            return result ?? false;
        }
        public event EventHandler LastResultNull;
    }
    

    Output:

    C, method1
    B, method1 (secondary)
    C, method2
    C, method1
    C, method2
    B, method2 (secondary)
    C, method1
    C, method2
    C, method1
    C, method2
    C, method1
    C, method2
    C, method1
    C, method2
    C, method1
    C, method2
    C, method1
    C, method2
    C, method1
    B, method1 (secondary)
    C, method2
    C, method1
    C, method2
    C, method1
    C, method2
    B, method2 (secondary)
    C, method1
    C, method2
    C, method1
    C, method2
    B, method2 (secondary)
    C, method1
    C, method2
    C, method1
    C, method2