Я хочу сделать что-то вроде этого. Но я не могу использовать IMyInterface в качестве общего типа для MyField, поскольку не предполагается, что он будет неуправляемым. Есть ли обходной путь?
public struct Main<T> where T: unmanaged
{
MyField<IMyInterface<T>> value;
public Main( Flag flag)
{
switch (flag)
{
case Flag.A:
value = new MyField<A<T>>();
break;
...
}
}
}
public struct MyField<T> where T: unmanaged { }
public struct A<T> : IMyInterface<T> where T: unmanaged {...}
public struct B<T> : IMyInterface<T> where T: unmanaged {...}
public struct C<T> : IMyInterface<T> where T: unmanaged {...}
public struct D<T> : IMyInterface<T> where T: unmanaged {...}
public interface IMyInterface<T> where T: unmanaged
{
// Some members.
}
Почему MyField имеет такие ограничения?
Если вы знаете, что тип не будет неуправляемым, не позволяйте ему реализовывать интерфейс. Альтернативно удалите ограничение из интерфейса, поскольку это не имеет особого смысла. Просто добавьте ограничение в реализацию, чтобы гарантировать, что для построения можно использовать только неуправляемые универсальные типы параметров.





Но я не могу использовать IMyInterface в качестве универсального типа для MyField, поскольку не предполагается, что он будет неуправляемым.
IMyInterface<T> не только «не обещает быть неуправляемым», он гарантированно управляем благодаря боксу. Когда вы работаете со структурами через интерфейс, они упаковываются в коробку. Отсюда следующее:
var x = new A<int>();
DoSomethingWithI(x);
void DoSomethingWithI(IMyInterface<int> p) => Console.WriteLine(p);
IL_0000: ldloca.s 0
IL_0002: initobj valuetype A`1<int32>
IL_0008: ldloc.0
IL_0009: box valuetype A`1<int32>
IL_000e: call void Program::'<<Main>$>g__DoSomethingWithI|0_0'(class IMyInterface`1<int32>)
IL_0013: ret
Один из способов обойти проблему — использовать два общих параметра:
public struct Main<T, TVal>
where T : unmanaged, IMyInterface<TVal>
where TVal : unmanaged
{
MyField<T> value;
// ...
}
Хотя использование становится немного неуклюжим:
var foo = new Main<A<int>, int>();
Не можете ли вы определить общую структуру как
struct MyField<IT, T> where IT: IMyInterface<T> where T: unmanaged?