Ограничение типа множественного типа (ИЛИ)

Читая это , я узнал, что можно позволить методу принимать параметры нескольких типов, сделав его обобщенным методом. В этом примере следующий код используется с ограничением типа, чтобы гарантировать, что «U» является IEnumerable .

 public T DoSomething(U arg) where U : IEnumerable { return arg.First(); } 

Я нашел еще несколько кодов, которые позволили добавить несколько ограничений типа, например:

 public void test(string a, T arg) where T: ParentClass, ChildClass { //do something } 

Тем не менее, этот код, как представляется, обеспечивает, чтобы этот arg был как типом ParentClass и ChildClass . Я хочу сказать, что arg может быть типом ParentClass или ChildClass следующим образом:

 public void test(string a, T arg) where T: string OR Exception { //do something } 

Ваша помощь ценится, как всегда!

Это невозможно. Однако вы можете определить перегрузки для определенных типов:

 public void test(string a, string arg); public void test(string a, Exception arg); 

Если они являются частью общего classа, они будут предпочтительнее общей версии метода.

Ответ Ботца на 100% правильный, вот короткое объяснение:

Когда вы пишете метод (общий или нет) и объявляете типы параметров, которые принимает метод, вы определяете контракт:

Если вы дадите мне объект, который знает, как делать множество вещей, которые знает тип T, я могу доставить либо «a»: возвращаемое значение объявляемого типа, либо «b»: какое-то поведение, которое использует этот тип.

Если вы попытаетесь присвоить ему несколько типов за раз (с помощью or) или попробуйте вернуть значение, которое может быть более одного типа, этот контракт становится нечетким:

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

Проблема в том, что когда вы входите в метод, вы не знаете, дали ли они вам IJumpRope или PiFactory . Кроме того, когда вы идете вперед и используете метод (при условии, что вы получили его, чтобы магически скомпилировать), вы не совсем уверены, есть ли у вас Fisher или AbstractConcreteMixer . По сути, это все более запутывает.

Решение вашей проблемы является одной из двух возможностей:

  1. Определите несколько методов, которые определяют каждое возможное преобразование, поведение или что-то еще. Это ответ Ботца. В мире программирования это называется перегрузкой метода.

  2. Определите базовый class или интерфейс, который знает, как делать все, что вам нужно для метода, и один метод принимает именно этот тип. Это может включать в себя завершение string и Exception в небольшом classе, чтобы определить, как вы планируете сопоставлять их с реализацией, но тогда все очень просто и легко читается. Я мог бы приехать через четыре года и прочитать ваш код и легко понять, что происходит.

Выбор, который вы выбираете, зависит от того, насколько сложным будет выбор 1 и 2, и насколько он может быть расширяемым.

Поэтому для вашей конкретной ситуации я собираюсь представить, что вы просто вытаскиваете сообщение или что-то из этого исключения:

 public interface IHasMessage { string GetMessage(); } public void test(string a, IHasMessage arg) { //Use message } 

Теперь все, что вам нужно, это методы, которые преобразуют string и Exception в IHasMessage. Очень просто.

Если ChildClass означает, что он получен из ParentClass, вы можете просто написать следующее, чтобы принять как ParentClass, так и ChildClass;

 public void test(string a, T arg) where T: ParentClass { //do something } 

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

 public interface ICommonInterface { string SomeCommonProperty { get; set; } } public class AA : ICommonInterface { public string SomeCommonProperty { get;set; } } public class BB : ICommonInterface { public string SomeCommonProperty { get; set; } } 

то вы можете написать свою общую функцию как;

 public void Test(string a, T arg) where T : ICommonInterface { //do something } 
  • Почему я могу вводить функции псевдонима и использовать их без кастинга?
  • Почему некоторые люди предпочитают «T const &» над «const T &»?
  • Как определить разные типы для одного и того же classа в C ++
  • Как вызвать общий метод с заданным объектом типа?
  • Строка не была признана действительным DateTime "format dd / MM / yyyy"
  • Разница между и
  • Что такое типы POD в C ++?
  • объект-литье с переменной типа
  • В чем разница между типом и classом?
  • Что такое тип данных uintptr_t
  • Является ли строка типом значения или ссылочным типом?
  • Давайте будем гением компьютера.