Вопрос по ограничениям дженериков
От: SergASh  
Дата: 12.04.16 10:27
Оценка:
Привет всем!

Есть два базовых generic класса, свойства которых должны ссылаться друг на друга.
Каким образом можно написать ограничения на типы так, чтобы в GenericCore в качестве
S разрешено было бы передать только наследника GenericShell<>?
Ну и наоборот, чтобы в GenericShell в качестве C можно было бы передать только
наследника GenericCore<>.

Хочется добиться того, чтобы ошибки покаывались именно при объявлении производных
классов, а не тогда, когда дело доходит до алгоритмов.

class GenericCore<S>   // Как ограничить S, чтобы он всегда был наследником GenericShell<>?
{
  public S Shell { get; set; }
}
class GenericShell<C>  // Как ограничить С, чтобы он всегда был наследником GenericCore<>?
{
  public C Core { get; set; }
}

class TestCore : GenericCore<TestShell>
{
}
class TestShell : GenericShell<TestCore>
{
}

class ProdCore : GenericCore<ProdShell>
{
}
class ProdShell : GenericShell<ProdCore>
{
}

class BadCore : GenericCore<object>  // Тут ошибки нет, а хотелось бы запретить параметризовать произвольным типом
{
}
class BadShell : GenericShell<object>
{
}

class Program
{
  static void Main( string[] args )
  {
    Simulation<TestCore, TestShell>();
    Simulation<ProdCore, ProdShell>();

    Simulation<BadCore, BadShell>();  // Так компилятор сделать не дает, но ошибку хотелось бы видеть раньше
  }

  static bool Simulation<C, S>()
    where C : GenericCore<S>, new()
    where S : GenericShell<C>, new()
  {
    var core = new C();
    var shell = new S();

    core.Shell = shell;
    shell.Core = core;

    return Validate( core, shell );
  }
   
  static bool Validate<C, S>( C core, S shell )
    where C : GenericCore<S>
    where S : GenericShell<C>
  {
    return core.Shell.Core == core && shell.Core.Shell == shell;
  }
}

Спасибо.
Re: Вопрос по ограничениям дженериков
От: Sinix  
Дата: 12.04.16 11:34
Оценка: 11 (2)
Здравствуйте, SergASh, Вы писали:

SAS>Привет всем!


SAS>Есть два базовых generic класса, свойства которых должны ссылаться друг на друга.

    public class ShellBase<TShell, TCore>
        where TShell : ShellBase<TShell, TCore>
        where TCore : CoreBase<TShell, TCore>
    {
        public TCore Core { get; set; }
    }

    public class CoreBase<TShell, TCore>
        where TShell: ShellBase<TShell, TCore>
        where TCore : CoreBase<TShell, TCore>
    {
        public TShell Shell { get; set; }
    }

    public class MyShell : ShellBase<MyShell, MyCore>
    {
    }
    public class MyCore : CoreBase<MyShell, MyCore>
    {
    }

    // ...
    var a = new MyShell();
    var b = new MyCore();
    a.Core = b;
    b.Shell = a;
    Console.WriteLine(a.Core.Shell.Core.Shell == a);
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.