Visual Studio 2015扩展方法调用方法组

时间:2015-09-02 10:14:25

标签: c# visual-studio-2015 extension-methods method-group

我有一个像

这样的扩展方法
public static void RemoveDetail<TMaster, TChild>(this TMaster master, TChild child)
        where TMaster : class, IMaster<TChild>
        where TChild : class, IDetail<TMaster>;

我有两个班级

public class Principal : IMaster<Permission>
{
        public virtual IEnumerable<Permission> Permissions { get; }
}

public class Permission : IDetail<Principal>

我从方法public static void Foreach<T>(this IEnumerable<T> source, Action<T> action);接受的操作中调用 RemoveDetail

aPrincipal.Permissions.Foreach(x => aPrincipal.RemoveDetail(x));

ReSharper建议我用

等方法组替换此调用
aPrincipal.Permissions.Foreach(aPrincipal.RemoveDetail);

这在VS2013和之前的版本中运行良好但在VS2015中用

进行编译失败了
  

'Principal'不包含'RemoveDetail'的定义,并且没有扩展方法'RemoveDetail'可以找到接受类型'Principal'的第一个参数(你是否缺少using指令或汇编引用?)

有人有建议吗? 我是否必须更新所有用法并使ReSharper避免这种替换?

3 个答案:

答案 0 :(得分:7)

我能够重现你的问题

public interface IDetail<T>
{

}

public interface IMaster<T>
{

}

public class MyClass
{
    public void method()
    {
        Principal aPrincipal = new Principal();
        aPrincipal.Permissions.Foreach(x => aPrincipal.RemoveDetail(x)); // No suggestion from resharper
    }
}

public class Permission : IDetail<Principal>
{

}

public class Principal : IMaster<Permission>
{
    public virtual IEnumerable<Permission> Permissions { get; }
}

public static class Class
{
    public static void RemoveDetail<TMaster, TChild>(this TMaster master, TChild child)
        where TMaster : class, IMaster<TChild>
        where TChild : class, IDetail<TMaster>
    {

    }

    public static void Foreach<T>(this IEnumerable<T> source, Action<T> action)
    {

    }
}

resharper没有提出任何建议。所以可能你必须将你的Resharper更新到更新的版本。可能是一个现在修复的错误。

如果这不像你那样做。然后你必须提供更多信息。

当我尝试将其转换为方法组时,编译器也会出现相同的错误。所以这个问题可能仍然存在:为什么编译器无法做到这一点?

修改

要解决此问题,您必须从Principal内部调用RemoveDetail方法。所以让你的校长班这样。

public class Principal : IMaster<Permission>
{
    public virtual IEnumerable<Permission> Permissions { get; }

    public void RemoveDetail(Permission p)
    {
        Class.RemoveDetail(this, p);
    }
}

我认为有一种模糊的内部编译器(可能是bug)无法识别RemoveDetail方法。编译器如何尝试在Principal内找到它。因此,您可以在RemoveDetail内创建Principal并从那里调用静态RemoveDetail来解决此问题。

编辑2:

问题是泛型类型约束。

where TMaster : class, IMaster<TChild>

这使得编译器可以查看实现IMaster<TChild>和那个Principal的类。如果你删除这个where子句,它将解决问题。否则编译器希望它应该是Principal

如果您使用lambda,则可以消除这种歧义。

aPrincipal.RemoveDetail // compiler expects property/field/method in Principal
                        // but compiler forgets method group and static generic method!
x => aPrincipal.RemoveDetail(x) // this is no more like property or field
                                //but a method that is considered static generic method!

那就是C#6错误

答案 1 :(得分:1)

我于2015年9月3日向Microsoft提供了有关此主题的反馈:
https://connect.microsoft.com/VisualStudio/feedback/details/1747835/visual-studio-2015-extension-method-call-as-method-group

今天我收到了Neal [MSFT]的反馈意见:

  

这已在VS2015 Update 1中修复   它在这里被跟踪:https://github.com/dotnet/roslyn/issues/4970

答案 2 :(得分:-2)

我不知道它在VS2013中是如何运作的。 RemoveDetail是一种TMethod而非您的行动MyClass的方法。

应该是

z.ForEach(x => master.RemoveDetail(x);