簡體   English   中英

如何定義通用擴展方法

[英]How can I define a generic extension method

我試圖定義一個擴展方法,可以返回由調用定義的類型的對象。

期望的用途: Cat acat = guy.GiveMeYourPet<Cat>();

嘗試實施

我可以毫無困難地定義這樣的泛型方法:

public static T GiveMeYourPet<T>(Person a) { ... }

Cat acat = GiveMeYourPet<Cat>(guy);

或者像這樣的擴展方法:

public static Cat GiveMeYourPetCat<P>(this P self) where P : Person, ... { ... }

Cat acat = guy.GiveMeYourPetCat();

但是,當我嘗試做我真正想要的事情時:

public static T GiveMeYourPet<T, P>(this P self) where P : Person, ... { ... }

Cat acat = guy.GiveMeYourPet<Cat>();

編譯器期望GiveMeYourPet()接收2個類型的參數(即使通過調用對象的擴展方法隱式提供了guy

我能做些什么來完成這項工作?

請注意,我也嘗試顛倒定義參數的順序,但沒有任何變化:

public static T GiveMeYourPet<P, T>(this P self)

以下調用也不起作用,因為您無法在類型說明中進行方法調用:

Cat acat = guy.GiveMeYourPet<guy.GetType(), Cat>();

C#編譯器類型推斷並不像您希望的那樣復雜。 您必須在這樣的方法中明確指定這兩種類型:

void Main()
{
    int i = 0;
    bool b = i.GiveMeYourPet<bool, int>();
}

public static class MyExtensions
{
    public static T GiveMeYourPet<T, P>(this P self)
    {
        return default(T);
    }
}

如果你想避免明確指定兩者(我不會責怪你),你可能會嘗試將你的方法改為:

public static T GiveMeYourPet<T>(this IPetOwner self)

(使用此界面,您甚至不需要知道真實類型是什么;如果您這樣做,請使用asis )甚至:

public static T GiveMeYourPet<T>(this object self)

(並用asis

如果那不是一個選項,並且真實類型的guy (在你的例子中)不是靜態知道的(例如你只是將他作為一個object ),你可能不得不使用反射,例如:

MethodInfo method = typeof(MyExtensions).GetMethod("GiveMeYourPet");
MethodInfo generic = method.MakeGenericMethod(typeof(Pet), guy.GetType());
generic.Invoke(guy, null);

如果像guy.GiveMeYour.Pet<Cat>(); 可以工作你可以建立類似於代碼的2個級別:

public class GiveMeYourBuilder<P>
{
   public P Me {get;set;}
   public T Pet<T>() : where T: new()
   { return new T();}
}

public static PetExtensions 
{
    public GiveMeYourBuilder<P>(this P me)
    {
         return new GiveMeYourBuilder<P> { Me = me;}
    }
}

您不能部分指定泛型參數,要么它們都是推斷的,要么必須全部指定。 在這種情況下,您可以獲得的最接近的可能是返回一個中間對象,該對象帶有調用擴展方法的泛型Person類型,並在其上定義Get方法:

public class GiveContext<T> where T : Person
{
    public P MeYourPet<P>() where P : Pet
    {
        return default(P);
    }
}

public static GiveContext<T> Give<T>(this T person) where T : Person
{
    return new GiveContext<T>();
}

您可以使用如下:

var p = new Person();
Cat c = p.Give().MeYourPet<Cat>();

不幸的是,你不能這樣做。 如果編譯器無法全部解決它們,則需要鍵入所有類型參數。 C#編譯器並不那么聰明。 dynamic可以幫助:

public static T GiveMeYourPet<T>(this dynamic self)
{
    //in here check that self meets your constraints using is, as, etc.
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM