[英]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)
(使用此界面,您甚至不需要知道真實類型是什么;如果您這樣做,請使用as
或is
)甚至:
public static T GiveMeYourPet<T>(this object self)
(並用as
或is
)
如果那不是一個選項,並且真實類型的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.