2

我有三个班。一个名为 A 的接口,以及实现 A 的 B 和 C。B 也有 C 的实例。A 的方法不能为空。但是,C 可能会不时返回 null。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
{
?
}

由于某些性能问题,我不想抛出异常。由于无法将覆盖类的类型更改为可为空,如何实现 C 类?

4

4 回答 4

1

您能否强制您的 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(){
        //...
    }
}
于 2013-07-16T20:48:47.740 回答
1

最好不要C实现A,只包含获取相同数据并让它们返回的方法bool?。听上去B还是可以满足的A

如果这不是一个选项,我只会抛出一个异常并将其捕获到B.

于 2013-07-16T21:06:33.590 回答
1

有了上述严格的要求,我设法想出了一种愚蠢的解决方案,但是哦,好吧 - 这有点..

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;
}

输出

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
于 2013-07-16T21:24:49.403 回答
1

我只是同意其他评论者:您已经定义了一个接口,该接口定义了您可以从实现此接口的类中获得的结果。不,您想更改 hevaviour,这意味着您要么调整接口以满足新要求,要么在 C 类需要违反接口定义时抛出异常(null 不在 def -> 违规范围内)。

据我所知,异常没有性能损失,直到它们真正被抛出。所以你无法猜测在某些情况下处理异常或在所有情况下检查空值是否更好。

于 2013-07-16T21:03:34.387 回答