11

我有一个扩展方法,比如

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>

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

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

ReSharper 建议我用方法组替换此调用,例如

aPrincipal.Permissions.Foreach(aPrincipal.RemoveDetail);

这在 VS2013 和以前的版本中运行良好,但在 VS2015 中编译失败

“Principal”不包含“RemoveDetail”的定义,并且找不到接受“Principal”类型的第一个参数的扩展方法“RemoveDetail”(您是否缺少 using 指令或程序集引用?)

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

4

3 回答 3

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 更新到更新的版本。可能是现在已修复的错误。

如果这不是你的方式。那么你必须提供更多信息。

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

编辑:

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

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

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

我认为编译器内部存在一种无法识别RemoveDetail方法的模棱两可(可能是错误)。编译器如何尝试在其中找到它PrincipalRemoveDetail因此您可以通过在内部创建并从那里Principal调用静态来修复它。RemoveDetail

编辑2:

问题是泛型类型约束。

where TMaster : class, IMaster<TChild>

这使编译器可以查看实现的类IMaster<TChild>和 thats 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 错误

于 2015-09-02T11:26:08.610 回答
1

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

今天我从 Neal [MSFT] 那里得到了这个反馈:

这已在 VS2015 Update 1 中修复。在
此处进行跟踪:https ://github.com/dotnet/roslyn/issues/4970

于 2015-11-12T20:41:26.737 回答
-2

我看不到它在 VS2013 中是如何工作的。 RemoveDetailTMethod不是你的 Action的方法MyClass

它应该是这样的

z.ForEach(x => master.RemoveDetail(x);
于 2015-09-02T10:24:12.380 回答