简体   繁体   English

c#中可抽象类的非可空方法的可空实现

[英]nullable implemention of non-nullable methods of an abstract class in c#

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. 一个名为A的接口,以及实现A的B和C.另外B有一个C的实例.A的方法不能为空。 However, C may return null from time to time. 但是,C可能会不时返回null。 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). B类检查C实例的方法,如果C的返回值为null,它将返回自身值(来自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? 我怎样才能实现C类,因为我无法将override类的类型更改为nullable?

Can you force your B and C classes to implement an interface that defines if the call is safe and what to do if it's not? 您是否可以强制您的B和C类实现一个接口,该接口定义调用是否安全以及如果不安全该怎么办?

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

public interface IFallbackIfNotSafe {
    public bool IsSafe();
    public bool Fallback();
}

public class B : A, IFallbackIfNotSafe
{
    public C c {get;set;}

    bool override method1()
    {
        return c.IsSafe() ? c.method1() : Fallback();
    }

    bool override method2()
    {
        //...
    }

    public bool Fallback(){
        //...
    }

    public bool IsSafe(){
        // make sure this B instance is safe
    }
}

public class C : A, IFallbackIfNotSafe
{
    bool override method1()
    {
        //...
    }

    bool override method2()
    {
        //...
    }

    public bool IsSafe(){
        // make sure this C instance is safe
    }

    public bool Fallback(){
        //...
    }
}

i've just to agree the other commentors: you have defined an interface which defines the results you can expect from a class that implements this interface. 我只是同意其他评论员:你已经定义了一个接口,它定义了你可以从实现这个接口的类中得到的结果。 no you want to change the hevaviour which means that you either adjust your interface to meet the new requirements or throw an exception if your class C needs to violate the interface definition (null is not within def -> violation). 不想要更改hevaviour,这意味着您要么调整接口以满足新要求,要么在C类需要违反接口定义时抛出异常(null不在def - >违规内)。

exceptions have no perfomance penalty as far is i know until they are really thrown. 在我们确实被抛出之前,我所知道的例外没有性能损失。 so you can no guess if its better to handle exceptions in some cases or check for null values in all cases. 因此,您无法猜测在某些情况下是否更好地处理异常或在所有情况下检查空值。

It may be best to just not have C implement A and just contain methods to get the same data and have them return bool? 最好不要只有C实现A并且只包含获取相同数据的方法并让它们返回bool? . It sounds like B can still satisfy the contract layed out by A . 听起来B仍然可以满足A所规定的合同。

If that is not an option, I would just throw an exception and catch it in B . 如果那不是一个选项,我只会抛出异常并在B捕获它。

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM