Приведение к произвольной версии универсального класса

#c# #generics #casting

Вопрос:

У меня есть следующий класс:

 public class Impactablelt;Tgt; : where T : Spawnablelt;Tgt; {  protected T spawnable = Spawnablelt;Tgt;.Instance;   void DoSomethingIndependentOfT(){} }  

Причина, по которой я это реализовал, заключается в том, что Spawnable-это ленивый расширяемый синглтон. В Impactable у меня, конечно , есть методы, которые используют spawnable , но также и методы, которые я не хотел бы использовать извне путем приведения.

 public sealed class EnemySpawnable : Spawnablelt;EnemySpawnablegt; { }  public class MyEnemyA : Impactablelt;EnemySpawnablegt; { }  MyEnemyA enemy = new MyEnemyA(); Impactable x = enemy; x.DoSomethingIndependentOfT();  

Возможно ли добиться такого приведения в C# или мне придется перепроектировать свой код?

Комментарии:

1. По сути, вы уже сделали это в своем примере кода. Определите базовый класс Impactable Impactablelt;Tgt; , из которого он происходит, и поместите туда независимые материалы.

2. Это похищение-очевидное решение, не так ли xD .. Тем не менее, я хочу узнать, в целом, возможен ли такой кастинг

Ответ №1:

Нет, это не так. Ограничение аргумента типа на Impactable ( where ) предотвращает это. Но необходимый рефакторинг является нетривиальным и тривиальным. Решение состоит в том, чтобы продвинуть независимые от типа методы в базовый класс, который не требует специализации, например:

 public class Spawnablelt;Tgt; {  public static T Instance; }  public class Impactable {  internal void DoSomethingIndependentOfT() { } }  public class Impactablelt;Tgt; : Impactable where T : Spawnablelt;Tgt; {  protected T spawnable = Spawnablelt;Tgt;.Instance; }  public sealed class EnemySpawnable : Spawnablelt;EnemySpawnablegt; { }  public class MyEnemyA : Impactablelt;EnemySpawnablegt; { }  public class Program {  public static void Main()  {  MyEnemyA enemy = new MyEnemyA();  Impactable x = enemy;  x.DoSomethingIndependentOfT();  } }  

Даже если то, что вы намеревались, было бы возможно (или стало возможным в будущих версиях C#), все равно намного проще сделать это таким образом, потому что он самостоятельно документирует намерение (методы, которые не используют универсальные, не должны находиться в контейнере с ограниченным типом).

Комментарии:

1. Это блестящее и простое решение, которое отлично подходит для моей конкретной проблемы в Unity, большое спасибо