Как указать объект, относящийся к одному классу, но не к определенному подклассу?

class A
{

}

class B : A
{

}

void method(A that is not a B argument) {}
void generic_method(generic_class<A that is not a B> generic_argument) {}
void params_method(params A that is not a B[] params_arguments) {}

Есть ли какой-либо синтаксический способ сделать это? я понимаю, что могу просто сделать

if(argument is B)
    throw new ArgumentException("argument cannot be a B", "argument");

в начале первого метода и сделать это в foreach для второго и третьего, но мне интересно, есть ли какое-то ключевое слово или концепция ООП, которая улучшает это.

Ответ 1

Похоже, вы пытаетесь выразить противоположность ограничения, например:

var Foo<T>() where T : SomeClass

Это сдерживает T как SomeClass или подкласс 1... но вы пытаетесь сделать это явно не T.

Нет, боюсь, в С# такого ограничения нет.


1 Ну, по модулю предположения, что SomeClass - это класс, который начинается с; это может быть интерфейс, со значением, которое вы, вероятно, ожидаете.

Ответ 2

В С# такого ограничения не существует, потому что это плохая идея, в частности ее нарушение Принцип подстановки Лискова (один из SOLID)

Подстановка - принцип в объектно-ориентированном программировании. В нем указано, что в компьютерной программе, если B является подтипом A, тогда объекты типа A могут быть заменены объектами типа B (т.е. Объекты типа B могут быть заменены для объектов типа A) без изменения каких-либо желательных свойств этой программы

Если ваша программа явно отклоняет объекты типа B, то это явно нарушение LSP и сильное указание на неправильность полиморфизма - вероятно, B не должно наследоваться от A в первую очередь.

Ответ 3

Что-то вроде этого? Разумеется, интерфейс, по моему мнению, был бы лучше в этом случае:

public abstract class A1
{
  //shared things for A and B 

  public string Hello()
  {
     return "hello!";
  }
}

public class A : A1
{

}

public class B : A1
{

}

public void something(A foo)
{
   var bar = ((A1)foo).Hello(); // says hello
}