说我有一个泛型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 <T,TKey>仅使用单个泛型类型参数实现接口。我将在下面尝试说明,您可以决定是否值得做出妥协。
这是您现有的Watcher类。
public class Watcher<T, TKey> : IWatcher<TKey> where T : IWatchable<TKey>
{
public Watcher(IWatchable<TKey> target) { }
}
这是它需要实现的接口:
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 <TKey>作为返回类型,即使它正在构造Watcher <IWatchable <TKey>,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()));
这种方法可能不是您所要的(或者也许是您所希望的),但是我认为这是避免为许多常见情况明确指定类型的最佳方法。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句