扩展方法和通用约束的问题

发布于 2024-09-28 10:11:04 字数 1101 浏览 3 评论 0原文

我有一个基本接口和几个继承的接口。基接口有一些扩展方法,可以修改对象并返回基类的新实例(IChildA.Touch() => IBaseIBase.Touch() => IBase)。

对于一个继承路径(IChildB 和后代),我想实现返回与调用对象类型相同的对象的扩展方法(IGrandChildB.Touch() => IGrandChild)。为此,我想指定一个仅限于 IChildB 后代的通用扩展方法。

到目前为止,此方法有效,但现在编译器无法解析来自 IChildA 的调用。它尝试使用 IChildB 路径的扩展方法,但失败,而不是使用 IBase 接口的扩展方法。有没有一种优雅的方法来解决这个问题?

public interface IBase {}

public interface IChildA : IBase {}

public interface IChildB : IBase {}

public static class BaseExtensions
{
  public static IBase Touch(this IBase self) { return self; }
  public static T Touch<T>(this T self) where T : IChildB { return self; }
}

public static class TestClass
{
  public static void Test()
  {
    IChildA a = null;
    IBase firstTry = a.Touch();  //Cannot resolve to BaseExtensions.DoSomething(this IBase obj)
    IBase secondTry = ((IBase)a).Touch();  //Resolves to BaseExtensions.DoSomething(this IBase obj)

    IChildB b = null;
    IChildB touchedB = b.Touch();
  }
}

I have a base interface and several inherited interfaces. There are extension methods for the base interface that modify the object and return a new instance of the base class (IChildA.Touch() => IBase, IBase.Touch() => IBase).

For one inheritance path (IChildB and descendants) i want to implement extension methods that return an object of the same type as the calling object (IGrandChildB.Touch() => IGrandChild). For this i would like to specify a single generic extension method that is constrained to IChildB descendants.

This works so far, but now the compiler cannot resolve the call from IChildA. It tries to use the extension method for the IChildB path and fails instead of using the extension method for the IBase interface. Is there an elegant way to fix this?

public interface IBase {}

public interface IChildA : IBase {}

public interface IChildB : IBase {}

public static class BaseExtensions
{
  public static IBase Touch(this IBase self) { return self; }
  public static T Touch<T>(this T self) where T : IChildB { return self; }
}

public static class TestClass
{
  public static void Test()
  {
    IChildA a = null;
    IBase firstTry = a.Touch();  //Cannot resolve to BaseExtensions.DoSomething(this IBase obj)
    IBase secondTry = ((IBase)a).Touch();  //Resolves to BaseExtensions.DoSomething(this IBase obj)

    IChildB b = null;
    IChildB touchedB = b.Touch();
  }
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

迟到的我 2024-10-05 10:11:04

我不知道您的具体用例,但如果您删除非泛型方法并将泛型方法限制为 IBase,该示例仍将编译。

public interface IBase {}

public interface IChildA : IBase {}

public interface IChildB : IBase {}

public static class BaseExtensions
{
    public static T Touch<T>(this T self) where T : IBase { return self; }
}

public static class TestClass
{
    public static void Test()
    {
        IChildA a = null;
        IBase firstTry = a.Touch();

        IChildB b = null;
        IChildB touchedB = b.Touch();
    }
}

I don't know your concrete use-case, but the example will still compile if you drop the non-generic method and instead constrain the generic method to IBase.

public interface IBase {}

public interface IChildA : IBase {}

public interface IChildB : IBase {}

public static class BaseExtensions
{
    public static T Touch<T>(this T self) where T : IBase { return self; }
}

public static class TestClass
{
    public static void Test()
    {
        IChildA a = null;
        IBase firstTry = a.Touch();

        IChildB b = null;
        IChildB touchedB = b.Touch();
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文