2015-11-12 3 views
2

В Java это справедливо:C# mimic Java generic?

class Class1<T extends OtherType> { T t; ... } 

//Inside other class that has no relation to Class1 
private Class1 class1; //No type needed 

public void someOtherFunction (Class1 class1) //Works 
{ 
    this.class1 = class1; //May warn about invalid type casting 
    class1.someFunction(); 
} 

C# требует типа в тех же условиях:

class Class1<T> where T : OtherType { T t; ... } 

//Inside other class that has no relation to Class1 
private Class1<TYPE DEMANDED> class1; //I don't know generic what type, and honestly it doesn't matter. 

public void someOtherFunction (Class1 class1) //This is the definition I want to use, but C# Demands a type to class1 
public void someOtherFunction<T> (Class1<T> class1) where T : OtherType //C# Demands a type to class1 so I must specify a T 
{ 
    this.class1 = class1; 
    class1.someFunction(); 
} //This function is valid but then it still needs the type to store it. 

Есть ли способ, чтобы опустить тип? Нет необходимости знать тип, так зачем он нужен? Я не могу сделать Class1 типа OtherType, потому что точка родоначальника должна иметь неизвестный тип, который расширяет базу OtherType. Я могу обойти это, но это, безусловно, самое эффективное решение, если бы это была Java, и мне придется набирать cast как только фрейм для нескольких объектов, если это не сработает, что я волнуюсь, будет складываться быстро.

Фактический код, по запросу:

public abstract class Weapon { ... } 

public abstract class WeaponProxy<T> : MonoBehaviour where T : Weapon 
{ 
    protected T weapon; 

    public virtual void Update() 
    { 
     ... 
     holdingPlayer = player.getHUD().showPickup(player, this); 
     ... 
    } 

public abstract class GunProxy<T> : WeaponProxy<T> where T : Gun 
{ 

} 



public abstract class Weapon 
{ 
    private string weaponName; 
    private string weaponIdentifier; 
    private Player isHolding; 

    public string getWeaponName() { return weaponName; } 
    public Weapon(string weaponName, string weaponIdentifier) 
    { 
     this.weaponName = weaponName; 
     this.weaponIdentifier = weaponIdentifier; 
    } 

    public void playerPickedUp (Player player) 
    { 
     this.isHolding = player; 
    } 

    public void playerDropped() 
    { 
     this.isHolding = null; 
    } 
} 

public class Gun : Weapon 
{ 
    ... 
} 

public class HUD : MonoBehaviour 
{ 
    private WeaponProxy weapon; //C# Needs a type. Underlined in red as error 

    public PlayerProxy showPickup<T> (PlayerProxy player, WeaponProxy<T> weapon) where T : Weapon 
    { 
     this.weapon = weapon; 
     textPickupWeapon.text = "Hold '" + player.getPlayer().getControlScheme().getControlText(ControlScheme.CONTROLS.Interact) + "' to pick up " + weapon.getWeapon().getWeaponName(); 
     ... 
    } 
} 
+0

'class' и' object' зарезервированы на C#; не используйте их как имя переменной. –

+0

@EricLippert Я знаю, я исправлю это сейчас. Спасибо. –

+0

Не знаете, как работает Java, но в .NET общие типы с разными параметрами типа фактически являются разными типами. Эти «построенные общие типы» генерируются компилятором, поэтому параметр типа должен быть известен во время компиляции. Поэтому я не думаю, что использовать его так, как вы пишете, это возможно. Для получения дополнительной информации см. MSDN: https://msdn.microsoft.com/en-us/library/ms172192(v=vs.110).aspx – vesan

ответ

7

Ваш Java-код «действителен», потому что все дженерики в Java, на самом деле не-дженериков, так как дженерики Java являются только время компиляции трюк, без поддержки во время выполнения какого ,

Для java runtime, тип A<T> на самом деле A без параметров типа, поскольку java runtime фактически не поддерживает дженерики вообще.

Напротив, .NET CLR имеет встроенную поддержку родовых типов времени выполнения и, следовательно, он различает тип A и общий тип A<T>.

В C#, если вы хотите не-дженерик типа Class1, просто объявить:

class Class1 
{ 
    //Whatever members that don't require a type parameter, 

    void SomeFunction() { /* ... */ } // Please use proper casing. 
} 

тогда, если вам нужна общая версия этого класса:

class Class1<T>: Class1 
{ 
    T Content { get; set; } 
} 

сейчас вы сможете получить член типа Class1 в любом другом классе

class Example 
{ 
    Class1 instance; // Valid 

    public void someOtherFunction (Class1 class1) //Works 
    { 
     this.instance = class1; //Does not warn about anything because this is type safe. 
     class1.SomeFunction(); // Works 

     var content = class1.Content // Compile Error: type class1 does not have such member "Content" 
    } 
} 

Обратите внимание, что подход C# намного безопаснее, если вы используете не общую версию, вы можете получить доступ только к членам класса, которые определены в не общей версии, и не требуют параметра типа. Напротив, java абсолютно небезопасен и может привести к ужасным ошибкам во время выполнения из-за отсутствия реальной безопасности типов в дженериках.

+0

@AndrewNo Я смотрю код, который вы только что добавили в свой вопрос, и я не думаю, что это займет много перезаписи. Я даже не думаю, что это требует дженериков. Просто интерфейс. Все игроки должны быть «IPlayer», и все оружие должно быть «IWeapon». – mason

+0

@mason. На самом деле это не эквивалентно, потому что T должен быть объявлен как переменная в не общий класс, который побеждает цель. –

+0

@mason, интерфейс! Я об этом не думал. Я внесу изменения и немного отчитаюсь. Спасибо. –