2015-11-08 3 views
2

Я пытаюсь сделать следующее:Как ограничить общую функцию, чтобы принимать только некоторый тип классов

public class A 
{ 
} 

public class B 
{ 
} 

Где-то в проекте я хочу, чтобы это:

public class C 
{ 
    public T func<T>(T obj) [where T can be either of class A or class B] 
    { 
     obj.x = 100; 

     return obj; 
    } 
} 

Я ве пытался:

public T func<T>(T obj) where T: A, B 

, но это дает мне:

Ограничение класса типа «B» должно выполняться перед любым другим ограничением.

Может кто-нибудь объяснить мне, как сделать func принять только класс A или класс B?

+1

Если вы можете сделать базовый класс или интерфейс 'BaseForAandB', тогда вы сможете установить ограничение типа' where T: BaseForAandB' –

+1

. Вы можете использовать интерфейсы для этой цели, но вы не можете сделать это, если вы не можете измените классы. –

+1

Какова практическая проблема, которую вы пытаетесь решить, приняв «A» или «B»? Используете ли вы какую-то общность между двумя классами? Разве вы не хотите, чтобы другие классы получали функциональность, связанную с вашим общим классом, даже если они могли соответствовать требованиям родового? – dasblinkenlight

ответ

4

Точно так, как это описано в вопросе, эта работа лучше обрабатывается разрешениеперегрузки:

public class C 
{ 
    public A func(A obj) 
    { 
     obj.x = 100; 
     return obj; 
    } 

    public B func(B obj) 
    { 
     obj.x = 100; 
     return obj; 
    } 

} 

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

interface IBase 
{ 
    int x; 
} 

public class C 
{ 
    public IBase func(IBase obj) 
    { 
     obj.x = 100; 
     return obj; 
    } 
} 

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

2

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

public interface IFooBar 
{ 
    void DoThis(); 
} 

public class Foo : IFooBar 
{ 
    public void DoThis() 
    { 
     //Do something 
    } 
} 

public class Bar : IFooBar 
{ 
    public void DoThis() 
    { 
     //Do something 
    } 
} 

public class C 
{ 
    public T func<T>(T obj) where T : IFooBar 
    { 
     obj.DoThis(); 
     return obj; 
    } 
} 
+0

Хорошая работа, предполагающая использование общего интерфейса вместо базового класса. – bitxwise

+2

Почему бы не просто 'public IFooBar func (IFooBar obj) {obj.DoThis(); return obj;}'? –

+0

OP говорит, что пользователь не знаком с дженериками и по какой-то причине хочет использовать дженерики. Этот ответ объясняет, как это сделать. – singsuyash

0

Общие классы, как и любой другой класс, вы не можете (и не должны) иметь множественное наследование классов, вы можете наследовать один класс и несколько интерфейсов.

В вашем случае вы должны применить интерфейс к обоим классам и ограничить общие элементы этого интерфейса.

вы можете увидеть некоторые документы в: Constraints on Type Parameters (C# Programming Guide)

0
interface IMarkerInterface{} // there is a such pattern called marker 
          // interface . No need to have methods if there 
          // is no need for, A and B can just implement it 

public class A: IMarkerInterface 
{ 
} 

public class B: IMarkerInterface 
{ 
} 

public class C 
{ 
    public T func<T>(T obj).Where T:IMarkerInterface 
    { 
     obj.x = 100; 
     return obj; 
    } 
} 
0

public T func<T>(T obj) where T: A, B это означает, что T должна распространяться как A и B, но множественное наследование не является действительным в C#, поэтому он не будет работать.

Вы можете сделать одно из следующих, хотя:

  1. вы могли бы сделать A и B имеют общего предка через interface или abstract класс, но это будет модификация кода.

  2. Поскольку оба A и B имеют конструктор по умолчанию no-arg, вы можете использовать where T: new().

Кроме того, вы не можете сделать obj.x = 100;, поскольку нет никакого способа, чтобы гарантировать, что T будет иметь экземпляр переменной x.

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