c# - 避免显式泛型类型 C#

标签 c# generics generic-constraints

假设我有一个通用的 class有一个约束,其中 T必须实现IWatchable<TKey> ,有什么方法可以使用 Watcher无需显式声明 TKey类型,考虑到 T无论如何都会提供这个吗?

public class Watcher<T, TKey> where T : IWatchable<TKey>
{
}

public interface IWatchable<TKey>
{
    TKey Key { get; }
}

如果我想使用Watcher class我必须声明TKey无论如何,作为第二种类型。

var watcher = new Watcher<BeingWatched, int>();

public class BeingWatched : IWatchable<int> { ... }

或者

var watcher = new Watcher<AlsoBeingWatched<Guid>, Guid>();

public class AlsoBeingWatched<TKey> : IWatchable<TKey> { ... }

最佳答案

如果我理解正确,您本质上希望编译器从其中一种泛型类型推断出另一种泛型类型。您可以通过使用静态泛型构造方法来实现这一目标,但您必须妥协并让 Watcher 实现仅具有单个泛型类型参数的接口(interface)。我将尝试在下面进行说明,您可以决定是否值得做出妥协。

这是您现有的 Watcher 类..

public class Watcher<T, TKey> : IWatcher<TKey> where T : IWatchable<TKey>
{
    public Watcher(IWatchable<TKey> target) { }
}

这是它需要实现的接口(interface):

public interface IWatcher<TKey> { }

现在我们需要一个非泛型静态 Watcher 类,该类将包含一个仅需要一种类型参数的泛型方法:

public static class Watcher
{
    public static IWatcher<TKey> For<TKey>(IWatchable<TKey> target)
    {
        return new Watcher<IWatchable<TKey>, TKey>(target);
    }
}

请注意,类型签名将 IWatcher 作为返回类型,即使它正在构造 Watcher, TKey>。这个技巧允许我们只指定一个类型参数。

下一个技巧是依靠 C# 的类型推断,这样我们在调用“For”方法时就不必指定“TKey”类型。如果我们已经上课:

public class BeingWatched : IWatchable<int>
{
    public BeingWatched(int key)
    {
        Key = key;
    }

    public int Key { get; }
}

然后我们可以使用以下代码获取该实例的观察者:

var watcher = Watcher.For(new BeingWatched(123));

类型推断使我们不必显式编写

var watcher = Watcher.For<int>(new BeingWatched(123));

只要没有歧义,这个方法就有效。如果你有课

public class AlsoBeingWatched : IWatchable<int>, IWatchable<Guid>
{
    private readonly int _numberKey;
    private readonly Guid _guidKey;
    public AlsoBeingWatched(int numberKey, Guid guidKey)
    {
        _numberKey = numberKey;
        _guidKey = guidKey;
    }

    int IWatchable<int>.Key { get { return _numberKey; } }

    Guid IWatchable<Guid>.Key { get { return _guidKey; } }
}

然后

var watcher = Watcher.For(new AlsoBeingWatched(123, Guid.NewGuid()));

无法编译,你会得到错误

The type arguments for method 'Watcher.For<TKey>(IWatchable<TKey>)' cannot be inferred from the usage.

您必须明确指定

var watcher = Watcher.For<int>(new AlsoBeingWatched(123, Guid.NewGuid()));

var watcher = Watcher.For<Guid>(new AlsoBeingWatched(123, Guid.NewGuid()));

这种方法可能不太符合您的要求(或者也许不是您所希望的),但我认为这是避免必须为许多常见情况显式指定类型的最佳方法。

关于c# - 避免显式泛型类型 C#,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39243423/

相关文章:

c# - 为什么 IEnumerable<T> 在 C# 4 中是协变的?

java - 文件夹: fold method

java - 为什么接口(interface)的泛型方法可以在 Java 中实现为非泛型?

c# - DbContext 的自定义连接打开/关闭

c# - 具有多个文件的自定义表单数据到 Web API Controller

java - 无法理解如何创建链表数组

快速模式匹配

c# - 相关 if 条件由 && 运算符控制

c# - "Column out of Range"填充 Excel 工作表时出错

c# - 指定类本身的泛型类的基类约束