2013-07-16 4 views
1

У меня есть три класса. Интерфейс A, B и C, реализующий A. Также B имеет экземпляр C. Методы A не могут быть нулевыми. Однако C может время от времени возвращать null. Класс B проверяет методы экземпляра C, и если возвращаемое значение C равно null, оно возвращает значения self (значения из B).NULL-реализация непустых методов абстрактного класса в C#

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, так как я не могу изменить тип класса переопределения на nullable?

+2

Пожалуйста показать некоторый реальный код. Ваш пример не имеет смысла, поскольку оба метода возвращают 'bool', который никогда не может быть« null ». –

+0

Это точка. класс C считывает данные из базы данных SQL, которая может быть нулевой. в то время как класс B принимает данные из файла XMl. Значения хранятся как «истинные», «ложные» и «по умолчанию» в базе данных, но они также могут быть нулевыми. – beebee

+0

В этом случае 'C' просто не может реализовать' A', потому что он не соответствует контракту. –

ответ

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 
+0

Спасибо большое Аарон. Я признаю, что есть лучшие решения, и я знаю об этом. Проблема в том, что я не могу поставить это "?" в методе интерфейса. Я просто не могу, потому что у меня нет доступа к нему. – beebee

+0

обновил мой ответ, чтобы сделать его безумным, но мне нравится практиковать мое кодирование на таких вещах, поэтому спасибо! –

+0

удивительный Аарон! Спасибо. Ваш навык кодирования действительно качается. знак равно – beebee

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(){ 
     //... 
    } 
} 
+0

C.IsSafe не является простым. Как я уже сказал, значения записи базы данных могут быть «по умолчанию». В этом случае он вызовет функцию B. поэтому запись может быть такой: запись: «true», «false», «default». по умолчанию мне нужно вызвать метод B, а для «true» и «false» метод C получает вызов – beebee

+0

Я могу передать имя столбца в isSafe, но он по-прежнему звучит как взломать – beebee

+1

Вся ваша проблема кажется любопытной хакерской honest =) –

1

Я только согласовать другое commentors: вы определили интерфейс, который определяет результаты, которые вы можете ожидать от класса, который реализует этот интерфейс. no вы хотите изменить hevaviour, что означает, что вы либо настраиваете свой интерфейс для соответствия новым требованиям, либо генерируете исключение, если ваш класс C должен нарушать определение интерфейса (null не входит в def -> нарушение).

исключений нет штрафа за исполнение, насколько я знаю, пока они действительно не будут брошены. , так что вы не можете догадаться, лучше ли в некоторых случаях обрабатывать исключения или проверять нулевые значения во всех случаях.

1

Возможно, было бы просто не иметь C реализовать A и просто содержать методы получения одинаковых данных и вернуть их bool?. Похоже, B все еще может удовлетворить контракт, заключенный на A.

Если это не вариант, я просто выброшу исключение и поймаю его в B.

+0

Спасибо Cemaphor, я постараюсь обсудить его. – beebee

 Смежные вопросы

  • Нет связанных вопросов^_^