【问题标题】:How to get correct extension method for a generic class method?如何为泛型类方法获取正确的扩展方法?
【发布时间】:2014-09-11 20:45:41
【问题描述】:

我最近在编写代码时遇到了这个问题。有没有办法我们可以在基类中编写代码,以便根据类型识别正确的扩展方法?

namespace GenericsInheritance
{
    public class Animal { }

    public class Dinasaur : Animal { }

    public class Dragon : Animal { }

    public abstract class Zoo<T> where T : Animal
    {
        public virtual string IdentifyYourSelf(T record)
        {
            //Calling extension method
            string name = record.IdentifyYourSelf();
            return name;
        }
    }

    public class DinasaurZoo : Zoo<Dinasaur> 
    {
        //I could use this, just wanted to try if base class method does identify the correct extension method for the type.
        //public override string IdentifyYourSelf(Dinasaur record)
        //{
        //    return record.IdentifyYourSelf();
        //}
    }

    public class DragonZoo : Zoo<Dragon> { }

    public class AnimalZoo : Zoo<Animal> { }

    //Extensions methods class.
    public static class LieDetector
    {
        public static string IdentifyYourSelf(this Animal record) { return "Animal"; }

        public static string IdentifyYourSelf(this Dinasaur record) { return "Dinasaur"; }

        public static string IdentifyYourSelf(this Dragon dog) { return "Dragon"; }

        //It works if I use this.
        //public static string IdentifyYourSelf<T>(this T record) where T : Animal
        //{            
        //    if (record is Dinasaur) { var dinasaur = record as Dinasaur; return IdentifyYourSelf(dinasaur); }
        //    else if (record is Dragon) { var dragon = record as Dragon; return IdentifyYourSelf(dragon); }        
        //    else return "I do not exist";
        //}
    }

    public class FbiInterrogation
    {
        public static void Main(string[] args)
        {
            var animal = new Animal();
            var dinasaur = new Dinasaur();
            var dragon = new Dragon();
            var dinasaurZoo = new DinasaurZoo();
            var dragonZoo = new DragonZoo();
            var animalZoo = new AnimalZoo();

            string name = dinasaurZoo.IdentifyYourSelf(dinasaur); //Prints Animal expecting Dinasaur
            name = dragonZoo.IdentifyYourSelf(dragon); //Prints Animal expecting Dragon
            name = animalZoo.IdentifyYourSelf(animal); //Prints Animal

            Console.ReadKey();
        }
    }
}

【问题讨论】:

  • 扩展方法是根据调用它们的变量的静态类型来解析的,而不是运行时类型。所以你的问题的答案是“不”——你必须通过派生类中的重载来做到这一点。
  • 重载还是覆盖?
  • @phoog:把它放到一个答案中,因为它的答案。顺便说一下,它是覆盖,而不是重载。
  • @StefanSteinegger 感谢您的更正和建议。

标签: c# generics inheritance extension-methods


【解决方案1】:

扩展方法是根据调用它们的变量的静态类型而不是运行时类型来解析的。因此,您的问题的答案是“否”——您必须通过派生类中的覆盖或通过繁琐的类型检查来做到这一点,正如您在问题中指出的那样。

【讨论】:

    【解决方案2】:

    这实际上可以使用反射来实现,尽管我不确定这样做是否是最好的主意:

    public abstract class Zoo<T> where T : Animal
    {
        public virtual string IdentifyYourSelf(T record)
        {
            return typeof(LieDetector).GetMethod("IdentifyYourSelf", new[] {typeof(T)}, null).Invoke(record, new object[] {record}) as string;
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-12-21
      • 1970-01-01
      • 1970-01-01
      • 2014-04-02
      • 2010-09-09
      • 1970-01-01
      • 2011-04-14
      相关资源
      最近更新 更多