【问题标题】:Is it possible to have a method always return a value of the same type as the calling instance?是否可以让方法始终返回与调用实例相同类型的值?
【发布时间】:2020-11-16 03:03:58
【问题描述】:

我可能会在这里看到一些明显的东西,但是... 基本上,我需要能够定义一个接口或类,其中包含一个方法,当它被子类型继承、覆盖或实现时,其返回类型与继承/覆盖/实现类型匹配。

我认为如果这完全可能的话,那将是泛型类型参数,所以我最初想出了以下内容(使用接口和实现它的类作为示例):

public interface IFoo<CurrentType> where CurrentType : IFoo<CurrentType> {
    CurrentType Method();
}

public class Bar : IFoo<Bar> {
   public Bar Method() => new Bar(); 
}

是的,它只适用于一种子类型,但一旦你有了另一种......

// Bar is still an IFoo<Bar> and therefore satisfies the constraint despite not matching the implementing subtype
public class Raboof : IFoo<Bar> {
   public Bar Method() => new Bar(); 
}

有没有办法用泛型类型参数来做到这一点,或者甚至有可能以某种方式做到这一点?我只是忽略了一些明显的东西吗?任何帮助将不胜感激。让一个泛型类型参数与实例的子类型相匹配,在过去的很多情况下都会对我有所帮助,所以我真的很困惑,为什么我在找了几次之后都没有发现关于这个主题的问题。


编辑:由于对我到底想要什么有很多困惑,我搜索了一下,发现了一个与此类似的问题,但没有答案(这可能是我为什么没有之前找不到):Is it possible to use the type of 'this' in a generic as a constraint itself?。这个问题表明 Swift 有一个类似的功能,其中有一个“Self”数据类型,这正是我想要的。对该问题的评论与关于 C# 中可能是什么样子的提案相关联: https://github.com/dotnet/roslyn/issues/11773

where TSelf : this 泛型约束仅适用于抽象类和接口。具有this 约束的类型参数将被约束为实现/派生类型本身,或者是实现/派生类型上的另一个where TSelf : this 约束类型参数。当在派生之外使用时(例如键入变量),也允许进一步派生子。

所以,长话短说,这在 C# 中是不可能的(还没有?)。确实经常弹出的东西是我之前描述的模式,但正如我和this blogpost 已经说过的那样,它真的不是特别擅长它的工作。 所以,是的,我的问题得到了回答。令人遗憾的是,这还不存在,我希望这样的东西能够以某种方式实现,无论是通过泛型约束还是只是像 Swift 中的预定义类型,但我多年来一直想要这样的东西。我希望这可以帮助任何在理解我的问题时遇到问题的人或遇到同样问题的其他人。干杯。

【问题讨论】:

  • 等等 - 你的意思是基本上在运行时检查你自己的类型??? (因此,每个特定的子类都会有所不同。)
  • 这听起来可能是XY Problem。你能提供一些关于为什么你想这样做的细节吗?即这个能力能解决什么问题?
  • @RufusL 促使我提出这个问题的动机是我尝试创建一些自定义列表类型,包括一个接口IReadableList&lt;T&gt;,它声明了List&lt;T&gt; 拥有的大多数方法。其中的一部分也是,例如,GetRange 方法,当FooList&lt;T&gt; : IReadableList&lt;T&gt; 的实例使用它时我想返回一个FooList&lt;T&gt;,但当BarList&lt;T&gt; : IReadableList&lt;T&gt; 的实例使用它时返回一个BarList&lt;T&gt;。所以我想出了IReadableList&lt;T, List&gt; where List : IReadableList&lt;T, List&gt; 的方法,但正如我所说,这只是完成了一半的工作。
  • @Fattie 如果方法返回类型在运行时被解析,这对我来说是新的。
  • 嗨@Nyde - 我的意思是,你不是想在运行时找出实例的“类”吗?抱歉,有点混乱。

标签: c# oop generics inheritance


【解决方案1】:

我有 2 个例子,也许它们会有所帮助:

解决方案 1:

public interface IFoo<T>
{
    T Method();
}

public class Foo : IFoo<Foo>
{
    public Foo Method() => new Foo();
}

public class Bar : IFoo<Bar>
{
    public Bar Method() => new Bar();
}


// In programm:
Foo foo = new Foo();
Foo foo2 = foo.Method();

Bar bar = new Bar();
Bar bar2 = bar.Method();

解决方案 2

public interface IFoo<T>
{
    T Method();
}

public class Foo<T> : IFoo<T> where T : new()
{
    public T Method() => new T();
}

public class Bar
{

}


// In programm:
Foo<Bar> foo = new Foo<Bar>();
Bar bar = foo.Method();

我不知道这是否正是您正在寻找的,但也许它会有所帮助......

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-05-25
    • 2020-03-27
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多