C# 如何定义泛型扩展方法
我试图定义一个扩展方法,该方法可以返回调用所定义类型的对象 所需用途:C# 如何定义泛型扩展方法,c#,C#,我试图定义一个扩展方法,该方法可以返回调用所定义类型的对象 所需用途:Cat acat=guy.GiveMeYourPet() 尝试实施 我很容易定义这样的通用方法: public static T GiveMeYourPet<T>(Person a) { ... } Cat acat = GiveMeYourPet<Cat>(guy); public static Cat GiveMeYourPetCat<P>(this P self) where P
Cat acat=guy.GiveMeYourPet()代码>
尝试实施
我很容易定义这样的通用方法:
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();
以下调用也不起作用,因为类型指定中不能有方法调用:
Cat acat = guy.GiveMeYourPet<guy.GetType(), Cat>();
Cat acat=guy.GiveMeYourPet();
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);
}
}
(并使用as
或is
)
如果这不是一个选项,并且家伙
(在您的示例中)的真实类型不是静态已知的(例如,您只是将他作为对象
),您可能必须使用反射,例如:
MethodInfo method = typeof(MyExtensions).GetMethod("GiveMeYourPet");
MethodInfo generic = method.MakeGenericMethod(typeof(Pet), guy.GetType());
generic.Invoke(guy, null);
如果类似于guy.GiveMeYour.Pet()代码>将起作用您可以构建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;}
}
}
public类给了我你的构建者
{
公共P Me{get;set;}
公共T Pet():其中T:new()
{返回新的T();}
}
公共静态扩展
{
公共赠予我你的建筑商
(本页)
{
返回新的GiveMeYourBuilder
{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>();
}
public类给定上下文,其中T:Person
{
公共P MeYourPet()其中P:Pet
{
返回默认值(P);
}
}
公共静态上下文给定(此T个人),其中T:个人
{
返回新的给定上下文();
}
您可以像这样使用:
var p = new Person();
Cat c = p.Give().MeYourPet<Cat>();
var p=newperson();
猫c=p.Give().MeYourPet();
不幸的是,您不能这样做。如果编译器无法将它们全部计算出来,则需要键入所有类型参数。C#编译器并不聪明<代码>动态
可通过以下方式提供帮助:
public static T GiveMeYourPet<T>(this dynamic self)
{
//in here check that self meets your constraints using is, as, etc.
}
public static T给我你的宠物(这个动态的自我)
{
//在这里,使用is、as等检查self是否满足您的约束。
}
我认为您需要显式地将T作为参数传入—否则编译器将如何知道要返回的类型?您不能仅将某些参数设为隐式。要么全有,要么全没有。我认为扩展方法不适用于泛型this
类型;不过,第一个解决方案应该是可行的。您会在这种方法的实现中投入什么?我认为最好将其分为两个单独的1类型参数化方法。不仅如此,如果我不知道“guy”(在本例中是我)的类型,我如何传入这个参数的类型呢?@Alaindynamic
实际上是一个非常有用的语言功能。看看我的答案。我能够将我对P
的类型限制减少到一个单一界面,并使用您示例中的技术public static T GiveMeYourPet(这个IPetOwner自己)
-感谢您的想法。如果您对Give
有人的限制,最好在分机上有一个此人
。我觉得它解决不了任何问题,因为它是最初问题的第一次尝试
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;}
}
}
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>();
public static T GiveMeYourPet<T>(this dynamic self)
{
//in here check that self meets your constraints using is, as, etc.
}