避免传递扩展泛型类的泛型类型参数 [英] Avoid passing generic type parameter of class extending generic class

查看:167
本文介绍了避免传递扩展泛型类的泛型类型参数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个抽象类Creature,它接受一个泛型类型参数,由另外两个类Human和Spider扩展。每个子类都定义其父类的通用类型。



我坚持如何将子类作为父类的引用传递给方法。

  public interface IDamagable 
{
void OnSimpleHit();
}

public interface IStabAble:IDamagable
{
void OnKnifeStab();
}

public interface ISlapAble:IDamagable
{
void OnSlap();
}

公共抽象类生物< T>其中T:IDamagable
{
public abstract void Init(T damageListener);
}

公共抽象类人类:生物< ISlapAble>
{

}

公共抽象类Spider:Creature< IStabAble>
{

}

public class MainClass
{
public void Test()
{
List<蜘蛛> spiderList =新列表< Spider>();
列表< Human> humanList = new List< Human>();

PrintList< IDamagable>(spiderList); //参数`#1'不能转换
//`System.Collections.Generic.List<newAd.B_A_A>'表达式
//键入`System.Collections.Generic.List< newAd.A_A< ; newAd.I_B>>'
}

protected void PrintList< T>(List< Creature< T> list)
{

}
}

如果PrintList带2个泛型参数, (T> list>)其中T:生物< U> U:IDamagable
{

}

不想再传递U,因为T已经以U作为类型参数构建,例如Spider已经定义了Creature采用IStabAble的类型参数。

因此基本上,我坚持写如何编写这样的方法,以满足蜘蛛和人类的最少数量的通用参数。

Thanks

解决方案

我假设 PrintList 只需要只读的只进入列表。



解决方案是让 PrintList 方法接受一个 IEnumerable< Creature< T>>< / code>像这样:

  void PrintList< T>(IEnumerable< Creature T> list)其中T:IDamagable 
{
// ...
}

并且像这样调用它:

  PrintList(spiderList); 

因为泛型类型参数 T in IEnumerable< T>

创建一个 Cast 方法,可以在不同项目类型的枚举类型之间进行转换,如.NET 3.5,我们已经有了扩展方法这样的方法):

  public static IEnumerable< U> Cast< T,U>(IEnumerable< T> source)其中T:U 
{
foreach(源中的var项)
{
yield return item;
}
}

并且像这样使用它:

  PrintList(Cast< Spider,Creature< IStabAble>>(spiderList)); 


I have an abstract class Creature that takes a generic type argument, extended by two other classes Human and Spider. Each subclass defines the generic type of its parent.

I am stuck with how to pass a subclass as a reference of parent class to a method.

public interface IDamagable
{
    void OnSimpleHit();
}

public interface IStabAble : IDamagable
{
    void OnKnifeStab();
}

public interface ISlapAble : IDamagable
{
    void OnSlap();
}

public abstract class Creature<T> where T : IDamagable
{
    public abstract void Init(T damageListener);
}

public abstract class Human : Creature<ISlapAble>
{

}

public abstract class Spider : Creature<IStabAble>
{

}

public class MainClass
{
    public void Test()
    {
        List<Spider> spiderList = new List<Spider>();
        List<Human> humanList = new List<Human>();

        PrintList<IDamagable>(spiderList); // Argument `#1' cannot convert
        //`System.Collections.Generic.List<newAd.B_A_A>' expression 
        //to type `System.Collections.Generic.List<newAd.A_A<newAd.I_B>>'
    }

    protected void PrintList<T>(List<Creature<T>> list)
    {

    }
}

This doesnt throw error if PrintList took 2 generic arguments

protected void PrintList<T,U>(List<T> list) where T : Creature<U> where U : IDamagable
    {

    }

But then I don't want to pass U again, as T was already constructed with U as type parameter, e.g Spider already defined Creature to take type parameter of IStabAble.

So basically, I'm stuck with how to write the method such that it caters both Spider and Human with minimal number of generic parameters.
Thanks

解决方案

I am assuming that PrintList only requires read-only forward-only access to the list.

The solution is to make the PrintList method accept an IEnumerable<Creature<T>> like this:

void PrintList<T>(IEnumerable<Creature<T>> list) where T: IDamagable
{
    //...
}

And call it like this:

PrintList(spiderList);

Because the generic type parameter T in IEnumerable<T> is covariant, this will work.

In your special case, because you are using .NET 2.0 (which does not support covariant type parameters) this solution will not work. Here is a workaround:

Create a Cast method that can convert between enumerables with different item types like this (in .NET 3.5, we already have such method as an extension method):

public static IEnumerable<U> Cast<T, U>(IEnumerable<T> source) where T : U
{
    foreach (var item in source)
    {
        yield return item;
    }
}

And use it like this:

PrintList(Cast<Spider, Creature<IStabAble>>(spiderList));

这篇关于避免传递扩展泛型类的泛型类型参数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆