C# 泛型 - 我可以让 T 来自两个选择之一吗?

发布于 2024-09-06 10:43:23 字数 359 浏览 7 评论 0原文

假设我有以下类层次结构:

Class A {...}

Class B : A  {...}

Class C : A {...}

我目前拥有的是

Class D<T> where T : A {...}

,但我想要某种形式的东西

Class D<T> where T in {B,C}

这是由于一些奇怪的行为,我不负责 B 和 C 具有 A 中没有的通用方法,但是如果能够在 T 上的 D 中调用它们那就太好了。

注意:我无权访问 A、B 或 C 来编辑它们

Suppose I have the following class hierarchy:

Class A {...}

Class B : A  {...}

Class C : A {...}

What I currently have is

Class D<T> where T : A {...}

but I'd like something of the form

Class D<T> where T in {B,C}

This is due to some odd behavior I'm not responsible for where B and C have common methods which aren't in A, but it would be nice to be able to call them in D on T.

Note: I don't have access to A,B or C to edit them

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

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

发布评论

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

评论(7

稳稳的幸福 2024-09-13 10:43:23

你需要为B和C中的公共方法定义一个接口(我们称之为Ibc),让B和C实现这个接口,然后你可以编写:

Class D<T> where T : A, Ibc {...}

You need to define an interface for the common methods that are in B and C (lets call it Ibc), make B and C implement this interface, and then you can write:

Class D<T> where T : A, Ibc {...}
女皇必胜 2024-09-13 10:43:23

首先,如果 B 和 C 有共同的方法,那么它们不共享接口就是一个设计缺陷。也就是说,即使无法访问 B 和 C,您也可以解决该问题。
可以创建一个通用接口。假设您有:

public class A
{
}
public class B : A
{
    public void Start() { }
}
public class C : A
{
    public void Start() { }
}

您可以创建一个公共接口:

public interface IStartable
{
    void Start();
}

并在 B 和 C 的派生类上使用它:

public class BetterB : B, IStartable
{
}
public class BetterC : C, IStartable
{
}

如果按原样获取 B 和 C 实例,您可能无法实现这一点,但如果您创建它们,则可以考虑。事实上,对于 B 和 C 的专门类,您可以使用接口而不是 D

First, If B and C have common methods, it is a design flaw they don't share an interface. That said, you can fix that even without having access to B and C.
It is possible to create a common interface. Suppose you have:

public class A
{
}
public class B : A
{
    public void Start() { }
}
public class C : A
{
    public void Start() { }
}

You can create a common interface:

public interface IStartable
{
    void Start();
}

And use it on derived classes from B and C:

public class BetterB : B, IStartable
{
}
public class BetterC : C, IStartable
{
}

You may not be able to achieve that if you get B and C instances as is, but it can be considered if you create them. In fact, with specialized classes of B and C, you may use the interface instead of D<T>.

彼岸花似海 2024-09-13 10:43:23

这不是直接可能的。

正如其他人所建议的,您可以定义一个接口并在 BC 中实现它。

如果这不是一个选项(例如,如果这些类超出了您的控制范围),我可能建议是这样的:首先,从一个抽象类开始,其中包含您可以使用任何 T 源自 A。然后假设您有一些 BC 都存在的方法,但它们不属于 A 的一部分。在D中,您可以使这些抽象方法由子类实现:

public abstract class D<T> where T : A
{
    protected T _member;

    public void DoSomethingAllTsCanDo()
    {
        _member.DoSomething();
    }

    public abstract void DoSomethingOnlyBAndCCanDo();
}

然后您可以从基类继承每个类型BC并且重写抽象方法以提供适当的功能:

public class DB : D<B>
{
    public override void DoSomethingOnlyBAndCCanDo()
    {
        _member.DoSomethingOnlyBCanDo();
    }
}

public class DC : D<C>
{
    public override void DoSomethingOnlyBAndCCanDo()
    {
        _member.DoSomethingOnlyCCanDo();
    }
}

This isn't directly possible.

As others suggest, you could define an interface and implement it in both B and C.

If this isn't an option (e.g., if these classes are beyond your control), what I might suggest is this: first, start with an abstract class that includes all the functionality you can achieve with any T deriving from A. Then say you have some methods that exist for both B and C that aren't a part of A. In D you can make these abstract methods to be implemented by subclasses:

public abstract class D<T> where T : A
{
    protected T _member;

    public void DoSomethingAllTsCanDo()
    {
        _member.DoSomething();
    }

    public abstract void DoSomethingOnlyBAndCCanDo();
}

Then you can inherit from the base class for each type B and C and override the abstract method(s) to provide the appropriate functionality:

public class DB : D<B>
{
    public override void DoSomethingOnlyBAndCCanDo()
    {
        _member.DoSomethingOnlyBCanDo();
    }
}

public class DC : D<C>
{
    public override void DoSomethingOnlyBAndCCanDo()
    {
        _member.DoSomethingOnlyCCanDo();
    }
}
﹎☆浅夏丿初晴 2024-09-13 10:43:23

B 和 C 实现相同的接口吗?这可能是更好的路线。

Do B and C implement the same interface? That may be a better route.

茶花眉 2024-09-13 10:43:23

一些选项:

  1. 创建一个接口 IdrivenFromA,其中包含 BC 的通用方法。
    从你的问题看来这是不可能的
  2. D中将T转换为dynamic并动态调用方法
    如果您可以使用 .Net 4,这是最简单的解决方案
  3. D 测试中,您是否处理 BC、转换和调用
    将由编译器检查,并且可以从 .Net 2 开始
  4. 丹涛答案:为BD的具体实现> 和C,它们可以直接调用BC中的方法。 (我自己没想到这一点)。
    仅当“用户源”知道它正在处理 BC 并且不使用抽象 A 时才有效使用D。相反,它应该使用 DBDC。但我认为情况就是如此,否则你不需要泛型。

Some options:

  1. Make an interface IderivedFromA that contain the common methods from B and C.
    Looks like this is impossible from your question
  2. In D cast T to dynamic and call the methods dynamically
    The most easy solution, if you can use .Net 4
  3. In D test if the you deal with an B or C, cast, and call
    Will be checked by the compiler, and is possible from .Net 2
  4. The Dan Tao answer: Create a specific implementation of D<T> for B and C, these can call the methods from B and C directly. (Didn't think of this one myself).
    Will only work if the "user-source" knows it is dealing with B or C, and does not use the abstract A to use D<A>. Instead it should use DB or DC. But I think this is the case, otherwise you didn't need generics.
栩栩如生 2024-09-13 10:43:23

C# 中的 where 约束不允许您指定多个类作为选择。
另外,如果您要指定多个包含位置,那么它们都必须满足。没有用于约束的 OR 逻辑。
以下是规范: http://msdn.microsoft.com/en-us/ Library/bb384067.aspx

Grzenio 的答案似乎适合您。将公共行为提取到 B 和 C 的公共接口中。然后您可以使用该接口作为约束。

The where constrain in C# does not allow you to specify multiple classes as a choice.
Also if you will specify multiple where contains, then they both has to be satisfied. There is no OR logic for constrain.
Here is specification: http://msdn.microsoft.com/en-us/library/bb384067.aspx

Answers from Grzenio seems right for you. Extract common behavior into the common interface for B and C. Then you can use that interface as a constrain.

花期渐远 2024-09-13 10:43:23

由于您无权访问源代码,唯一真正的答案(除非您愿意因使用动态而失去安全性)是显式检查B< /code>/C 并强制转换。

Since you don't have access to the source, the only real answer (unless you are willing to lose safety by using dynamic) is explicitly check for B/C and cast.

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