避免显式泛型类型c#

避免显式泛型类型c#,c#,generics,generic-constraints,C#,Generics,Generic Constraints,假设我有一个泛型类,该类有一个约束,其中T必须实现IWatchable,考虑到T无论如何都会提供该约束,那么有没有任何方法可以使用Watcher而不必显式声明TKey类型 public class Watcher<T, TKey> where T : IWatchable<TKey> { } public interface IWatchable<TKey> { TKey Key { get; } } 或 var-watcher=new-watch

假设我有一个泛型
,该类有一个约束,其中
T
必须实现
IWatchable
,考虑到
T
无论如何都会提供该约束,那么有没有任何方法可以使用
Watcher
而不必显式声明
TKey
类型

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

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

var-watcher=new-watcher();
公共类也被监视:IWatchable{…}

如果我理解正确,您基本上希望编译器从一个泛型类型推断出另一个泛型类型。通过使用静态泛型构造方法,您可以与此保持一定距离,但您必须妥协,让Watcher实现一个只有一个泛型类型param的接口。我将试着在下面举例说明,你可以决定是否值得做出妥协

这是您现有的Watcher类

public class Watcher<T, TKey> : IWatcher<TKey> where T : IWatchable<TKey>
{
    public Watcher(IWatchable<TKey> target) { }
}
类型推断使我们不必显式地编写

var watcher = Watcher.For<int>(new BeingWatched(123));
如果不编译,您将得到错误

The type arguments for method 'Watcher.For<TKey>(IWatchable<TKey>)' cannot be inferred from the usage.
无法从用法推断方法“Watcher.for(IWatchable)”的类型参数。
您必须显式地指定

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

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

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

考虑类型系统将允许类型多次实现泛型接口(使用不同的类型参数)@Damien_不信者因此如果
被监视
实现
IWatchable
IWatchable
,那么
监视者将不知道在
被监视
中使用哪个实现?这就是它需要显式的原因。
where
子句只用于约束检查,不用于类型解析。。。但是,您是否需要在
观察者
上了解
T
?也许将一个观察者注册为
public class watcher
并使用
IWatchable
而不是具体的类型就足够了?有趣的解决方法,这看起来确实有些过分,但现在我明白了为什么必须明确声明该类型。谢谢你!
public static class Watcher
{
    public static IWatcher<TKey> For<TKey>(IWatchable<TKey> target)
    {
        return new Watcher<IWatchable<TKey>, TKey>(target);
    }
}
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()));