2012-07-22 66 views
2

我有子彈:泛型協方差變通辦法?

public LaserBullets : Projectile 

我有槍,從與與派生槍響子彈型基武器繼承:

public LaserWeapon : Weapon<LaserBullets> 

我必須建立在當前武器屬性玩家的:

public Weapon<Projectile> CurrentWeapon 
{ 
    set { currentWeapon = value; } 
} 

這失敗(不能隱式轉換LaserWeaponWeapon<Projectile>

player.CurrentWeapon = new LaserWeapon(); 

我讀過關於不支持C#中的某些協方差,但我不想認爲我卡在這裏。有什麼方法可以讓我的情況發揮作用嗎?我試圖在玩家類中保持基礎武器,但在另一個類中使用更具體的武器。

我試着爲LaserWeapon創建自己的投射操作符,但是我得到了無法投射到基類的錯誤。

+0

我以爲這會奏效,但我會承認你沒說的。如果你製作武器的'Weapon'基礎類是什麼?然後讓'CurrentWeapon'只是一個'Weapon'? – 2012-07-22 22:44:38

+0

我會看到它的。但是這可能是個問題,因爲武器有一個抽象方法Fire()返回TProjectile。 'Player'在基類上調用這個方法。這導致另一種類型的協方差問題,其中指定基本返回類型並用派生返回類型重寫也具有編譯時問題。 – 2012-07-22 22:55:34

+0

我相信@JonathonReinhart是正確的 - 根據我的經驗,在這種情況下,我總是使用非泛型基類或接口。 – 2012-07-22 22:56:24

回答

5

我相信,如果Weapon<T>被宣佈像這樣一個協接口你的例子會工作:

public interface Weapon<out TProjectile> 
{ 
} 

這隻會在哪裏工作TProjectile被用作返回值,例如:

TProjectile Fire(); 

但將不是工作,其中TProjectile被用作輸入參數,例如:

LoadClip(IEnumerable<TProjectile> ammo); 

從您的意見,我可以看到你的一般返回值後的時候,所以要的界面如下:

public interface IWeapon<out TProjectile> where TProjectile : Projectile 
{ 
    TProjectile Fire(); 
} 

然後使用這個接口的實現;沒有什麼能阻止你擁有一個有用的基類,例如

public abstract class Weapon<TProjectile> : IWeapon<TProjectile> where TProjectile : Projectile 
{ 
    public abstract TProjectile Fire(); 
} 

只要您的播放器類是沿着線:

public class Player 
{ 
    public IWeapon<Projectile> CurrentWeapon { get; set; } 
} 

這允許你仍然使用CurrentWeapon.Fire()將返回的Projectile一個實例。

+0

非常感謝。我從你的回覆中瞭解了很多,它似乎適用於我的特定場景。 – 2012-07-23 01:20:37

1

製作Weapon<T>繼承的非泛型類Weapon。在代碼中使用該類而不是Weapon<Projectile>