我有以下对象
class Magazine
{
String intendedGunId {get;}//Returns some Gun.weaponID;
int size {get;}
//Implementation
}
class Gun
{
public enum FireModes
{
Bolt,
Semi,
FullAuto
}
public FireModes fireMode { get; private set; }
Magazine magazine;
public Magazine reload(Magazine newMag)
{
if (magazine.intendedGunId == newMag.intendedGunID)
{
Magazine temp = magazine;
this.magazine = newMag;
return temp;
}
return newMag;
}
//Other implementation
}
class AKMag : Mag
{
//Implementation
}
class AK : Gun
{
//Implementation
}
我正在设计一把枪和一个弹匣,它应该总是用于多支不同的枪。
我不认为将Magazine变量保持为T : Magazine
而不仅仅是Magazine是一个明智的想法,因为在重新加载时,几乎任何Magazine都可以被接受,而且它感觉不像是安全的代码;我觉得黑客很容易利用这一点。
我尝试了以下通用:
class Gun<T> where T : Magazine
{
T magazine;
//Other implementation
}
class AK : Gun<AKMag>
{
}
问题是,一旦我使用泛型,就不可能存储Gun<Magazine>
变量,因为在某个时候,编译器会说"无法从Gun<AKMag>
转换为Gun<T> where T : Magazine
。"
基本上,每把枪都有自己的弹匣,只属于自己的枪。我很难正确地实现这一点,可能是因为对C#泛型或C#继承缺乏了解。
编辑:对于通用枪,以下场景不起作用:
Gun<Magazine> someGun;
public void func (Gun<Magazine> gun)
{
this.someGun = gun;
}
//In another class
AK<AKMagazine> someAK;
public void func2 ()
{
func1 (someAK); //Error: "Can not convert from `Gun<AKMag>` to `Gun<T> where T : Magazine`."
}
编辑:我决定最好的方法是检查一下杂志。GetType()==newMag.GetType()只要mag要更改,接口也可以工作。
只使用普通的旧接口怎么样?
class Program
{
static void Main(string[] args)
{
Gun myGun = new AK();
Console.WriteLine(myGun.load(new AK_Mag())); // true
Console.WriteLine(myGun.load(new ShotGun_Mag())); // false
func2();
}
static Gun someGun;
static void func1(Gun gun)
{
someGun = gun;
}
public static void func2()
{
Gun someAK = new AK();
someAK.load(new AK_Mag());
func1(someAK);
}
}
public class AK : Gun
{
public bool load(Mag mag)
{
if (mag == null)
return false;
if ( mag.GetType() != typeof(AK_Mag))
{
return false;
}
return true;
}
public void shoot(int x, int y, int z)
{
throw new NotImplementedException();
}
public bool setFireMode(Gun.FireMode mode)
{
this.mode = mode;
return true;
}
}
public class AK_Mag : Mag
{
public int Remain()
{
throw new NotImplementedException();
}
}
public class ShotGun_Mag : Mag
{
public int Remain()
{
throw new NotImplementedException();
}
}
public interface Gun
{
public enum FireMode { Manual, Burst };
bool load(Mag mag);
void shoot(int x, int y, int z);
bool setFireMode(FireMode mode);
}
public interface Mag
{
int Remain();
}
尝试这种方法:
class Magazine
{
public readonly Type GunType; // Used for identification of compatible gun type.
public Magazine (Type gunType)
{
this.GunType = gunType;
}
}
class Gun
{
// Factory method
public Magazine CreateMagazine()
{
return new Magazine(this.GetType());
}
public Magazine Reload(Magazine newMag)
{
// Test whether the magazine is compatible with the current gun.
if (newMag.GunType != this.GetType()) {
throw new ArgumentException();
// Or just reject the new magazine and keep the current one.
}
// Your reload logic goes here ...
}
}
泛型的问题是,即使A
和B
之间存在继承关系,T<A>
和T<B>
这两种类型也不能进行赋值兼容。另一个问题是,泛型在编译时得到完全解决。你需要一个更动态的方法。在游戏中,您可能希望将枪支和弹匣存储在用户的库存中,并以相同的方式处理所有枪支和弹仓类型。可以在运行时以完全动态的方式将所需类型存储为System.Type
。
你可以创建和使用这样的杂志:
Gun gun = new AK();
Magazine magazine = gun.CreateMagazine();
Magazine other = gun.Reload(magazine);