Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/286.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/jpa/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何定义泛型扩展方法_C# - Fatal编程技术网

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”(在本例中是我)的类型,我如何传入
这个
参数的类型呢?@Alain
dynamic
实际上是一个非常有用的语言功能。看看我的答案。我能够将我对
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.
}