c#转换为接口
本文关键字:接口 转换 | 更新日期: 2023-09-27 18:17:49
是否可以定义如何将内置对象转换为c#中的接口?接口不能定义操作符。我有一个非常简单的接口,允许索引访问,但不允许突变:
public interface ILookup<K, V>
{
V this[K key] { get; }
}
我希望能够将Dictionary<K, V>
转换为ILookup<K, V>
。在我理想的梦想世界中,它看起来像:
//INVALID C#
public interface ILookup<K, V>
{
static implicit operator ILookup<K, V>(Dictionary<K, V> dict)
{
//Mystery voodoo like code. Basically asserting "this is how dict
//implements ILookup
}
V this[K key] { get; }
}
我想出的变通办法是:
public class LookupWrapper<K, V> : ILookup<K, V>
{
private LookupWrapper() { }
public static implicit operator LookupWrapper<K, V>(Dictionary<K, V> dict)
{
return new LookupWrapper<K, V> { dict = dict };
}
private IDictionary<K, V> dict;
public V this[K key] { get { return dict[key]; } }
}
这工作,这意味着我现在可以直接从字典转换到我查找,但男孩它感觉很复杂…
是否有更好的方法强制转换到接口?
由于接口不能包含实际代码,因此需要一些类来"托管"强制转换的代码。这可以是一个实现接口的类(很明显),也可以是一个包装器类,就像您使用的包装器一样。没有第三种选择。
¹你"调用"强制转换的方式可以不同(例如,你可以在扩展方法后面隐藏LookupWrapper
的构造),但这不会改变事情。
如果您对Dictionary有任何控制,您可以将其子类化并在子类中重写this[]
。然后用你的新字典代替。net字典
感谢@MBabcock的评论,我意识到我想错了。我将接口提升为完全on类,如下所示:
public class Lookup<K, V>
{
private readonly Func<K, V> lookup;
protected Lookup(Func<K, V> lookup)
{
this.lookup = lookup;
}
public static implicit operator Lookup<K, V>(Dictionary<K, V> dict)
{
return new Lookup<K, V>(k => dict[k]);
}
public V this[K key]
{
get { return lookup(key); }
}
}
像这样的任何进一步的转换,我可以简单地添加一个隐式操作符
最好是使用扩展方法和包装器类…
public interface ILookup<K, V>
{
V this[K key] { get; }
}
public class DictWrapper<K, V> : ILookup<K, V>
{
Dictionary<K, V> dictionary;
public DictWrapper(Dictionary<K, V> dictionary)
{
this.dictionary = dictionary;
}
public V this[K key]
{
get { return dictionary[key]; }
}
protected internal Dictionary<K, V> InnerDictionary { get { return dictionary; } }
}
public static class Extensions
{
public static ILookup<K, V> ToLookup<K, V>(this Dictionary<K, V> dictionary)
{
return new DictWrapper<K, V>(dictionary);
}
}
class Program
{
static void Main(string[] args)
{
Dictionary<string, int> data = new Dictionary<string, int>();
data.Add("Office", 100);
data.Add("Walls", 101);
data.Add("Stair", 30);
ILookup<string, int> look = data.ToLookup();
}
}
这是一种相当令人震惊的语言堕落,但有一种方法。我假设你基本上是在尝试将一个接口应用于一个已经拥有你想要的签名的类,你只是想要一个子集(就像你的例子一样)。
你可以使用一个TransparentProxy/RealProxy对在运行时创建一个类来实现任何接口(或MarshalByRef对象)。你需要实现一个抽象方法来处理调用,但是你可以使它足够泛型,从而能够处理这种情况。
我们遇到了一个非常糟糕包装的库的类似问题(我们必须使用反射来进行每个方法调用)。因此,我们没有编写大量自定义反射代码,而是编写了通用情况,然后编写了一堆与签名匹配的接口。然后我们直接使用接口。我们甚至可以自动包装/取消包装对象,这样我们就可以让我们的接口方法返回其他接口,这一切都可以正常工作。
在http://blog.paulhounshell.com/?s=Duck