Использование дженериков не означает, что вы можете использовать утка печатать. C# является статически типизированным языком, так что вам нужно сделать что-то вроде следующего:
Во-первых, определить интерфейс, который определяет общий интерфейс A
и B
:
interface IHasAB
{
int A { get; }
int B { get; }
}
Тогда, ваши struct
реализуем этот интерфейс:
struct A : IHasAB
{
public A(int a, int b)
{
A = a;
B = b;
}
public int A { get; } // Note: `A` and `B` are now properties, not fields
public int B { get; } // like before; interfaces do not allow you to declare fields.
// Note also: mutable structs are a bad idea! That's why we implement
// `A` and `B` as read-only properties.
}
struct B : IHasAB { … } // same as for `A`
Теперь вы можете реализовать метод bar
с дополнительным параметром ограничения общего типа where T : IHasAB
:
void bar<T> (T input) where T : IHasAB
{
var a = input.A;
}
Ограничение на T
позволяет компилятору знать, что он может ожидать T
быть. Теперь он знает, что T
- это тип, который реализует IHasAB
и поэтому имеет два свойства A
и B
(так как это интерфейс состоит из). Вот почему теперь вы можете получить доступ к .A
по адресу input
.
Обратите внимание, что вам не обязательно нужно сделать bar
родовое:
void bar(IHasAB input)
{
var a = input.A;
}
В этом последнем случае, обратите внимание, что input
теперь ссылка типизированных параметров. Если вы передали один из своих структур A
или B
этому методу, он должен быть помещен в коробку (т. Е. Повернут из типа значения в ссылочный тип). В этом есть некоторые накладные расходы.
Я не буду углубляться в опасности изменчивых структур и бокса, которые могут легко произойти в ситуациях, когда структуры реализуют интерфейсы, поскольку это совсем другое дело; Я бы рекомендовал вам потратить немного времени на изучение этих тем. ;-)
Вам нужно будет использовать refection для получения свойств –
Почему вы хотите использовать дженерики здесь? –
Вы можете использовать общий интерфейс. –