为C#接口定义隐式和显式转换

有没有办法在C#中编写基于接口的代码(即使用接口而不是类作为接受和传递的类型)而不放弃使用隐式转换等内容? 这里有一些示例代码 – 已经删除了很多,但这些是相关的部分。

public class Game { public class VariantInfo { public string Language { get; set; } public string Variant { get; set; } } } 

在ScrDictionary.cs中,我们有……

  public class ScrDictionary: IScrDictionary { public string Language { get; set; } public string Variant { get; set; } public static implicit operator Game.VariantInfo(ScrDictionary s) { return new Game.VariantInfo{Language=sd.Language, Variant=sd.Variant}; } } 

和界面……

  public interface IScrDictionary { string Language { get; set; } string Variant { get; set; } } 

我希望能够使用IScrDictionary而不是ScrDictionary ,但仍然可以隐式地将ScrDictionary转换为Game.VariantInfo 。 此外,尽管通过给IScrDictionary提供类型为IScrDictionary的属性可能有一种简单的方法来完成这项工作, Game.VariantInfo我的问题更为普遍: 有没有办法在接口上定义强制转换或运算符重载? (如果没有,在不放弃面向接口的设计的情况下,维护此function的C#方式是什么?)

您无法在接口上定义强制转换或运算符重载。 由于接口是一个描述永远可用的成员的契约(作为对该接口的显式强制转换或作为公共成员),你不能再依赖接口来包含任何类型的内置逻辑,例如如何转换或者运营商将如何使用该界面执行。

您仍然可以从实现接口的抽象基类inheritance,并提供转换或运算符重载所需的逻辑。 这不违反面向接口的设计。 不从公共基类inheritance但实现接口的类仍然需要独立地实现它们自己的隐式转换和运算符重载。 如果您希望集中逻辑以使用通常实现接口的类,您可以在C#3.0 + / .NET XP Fx 3.5中使用扩展方法(或在以前的版本中使用静态方法)。 下面我用一个实用程序类和两个类Foo和Bar来演示它,它们没有共同的祖先。 它们共享包含实用程序函数Add的代码,因此您不必在两个类中重复此实现。

 public interface IInterface { int X { get; set; } int Y { get; set; } } public static class IInterfaceTHelper { public static IInterface Add(this IInterface a, IInterface b) where T : new() { var ret = (IInterface)new T(); ret.X = aX + bX; ret.Y = aY + bY; return ret; } } class Foo : IInterface { public int X { get; set; } public int Y { get; set; } public static IInterface operator +(Foo a, IInterface b) { return a.Add(b); } } class Bar : IInterface { public int X { get; set; } public int Y { get; set; } public static IInterface operator +(Bar a, IInterface b) { return a.Add(b); } } class Program { static void Main(string[] args) { var foo = new Foo { X = 5, Y = 3 }; var bar = new Bar { X = 3, Y = 5 }; var result = foo + bar; Console.WriteLine(result.GetType().Name + " " + result.X + " " + result.Y); result = bar + foo; Console.WriteLine(result.GetType().Name + " " + result.X + " " + result.Y); Console.ReadLine(); } } 

如果您的界面包含的不仅仅是违反合同设计的合同。

实现此目的的一种方法是,如果存在您可能经常需要定义的转换/转换,则作为您的接口上的方法,例如

 public interface ISomeInterface { TargetType ToTargetType(); } 

然后在抽象基类中,您可以定义一个implict / explicit强制转换,并让ToTargetType()的实现只调用ToTargetType()运算符,例如

 public abstract class SomeAbstractClass : ISomeInterface { public TargetType ToTargetType() { return (TargetType)this; } public static explicit operator TargetType(SomeAbstractClass obj) { //Actual cast logic goes here } } 

这样,您可以确保实现提供了一种转换为必要类型的方法,以便纯接口驱动的代码可以调用接口方法来进行转换。 但是,使用具有定义的强制转换运算符的接口的具体实现的代码可以使用它们