为C#接口定义隐式和显式转换 [英] Defining implicit and explicit casts for C# interfaces

查看:214
本文介绍了为C#接口定义隐式和显式转换的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

Is there a way to write interface-based code (i.e. using interfaces rather than classes as the types accepted and passed around) in C# without giving up the use of things like implicit casts? Here's some sample code - there's been a lot removed, but these are the relevant portions.

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

在ScrDictionary.cs中,我们有... 。

And in ScrDictionary.cs, we have...

 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 一个类型为 Game.VariantInfo my的属性,可能有一种简单的方法来完成这项工作。更一般的问题是:有没有办法在接口上定义强制转换或运算符重载?(如果没有,在不放弃面向接口的设计的情况下,维护此功能的C#方法是什么?)

I want to be able to use IScrDictionary instead of ScrDictionary, but still be able to implicitly convert a ScrDictionary to a Game.VariantInfo. Also, while there may be an easy way to make this work by giving IScrDictionary a property of type Game.VariantInfo my question is more generally: Is there a way to define casts or operator overloading on interfaces? (If not, what is the proper C# way to maintain this functionality without giving up interface-oriented design?)

推荐答案

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

You cannot define casts or operator overloading on interfaces. Since an interface is a contract that describes the members which will always be available (either as an explicit cast to that interface or as public members) and nothing more you cannot rely on interfaces to contain any sort of built in logic such as how to cast or how operators will perform with that interface.

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

You can still inherit from an abstract base class which implements the interface and provides the logic you need for casts or operator overloading. This doesn't violate interface oriented design. Classes which do not inherit from the common base class but implement the interface will still need to independently implement their own implicit casts and operator overloads. If you wish to centralize the logic for working with classes that commonly implement an interface you can do so in C# 3.0+/.NET Fx 3.5 with extension methods (or in previous versions with static methods). Below I demonstrate this with a utility class and two classes, Foo and Bar, which don't have a common ancestor. They share the code which comprises the utility function Add so you don't have to repeat this implementation in both classes.

public interface IInterface
{
    int X { get; set; }
    int Y { get; set; }
}

public static class IInterfaceTHelper
{
    public static IInterface Add<T>(this IInterface a, IInterface b) 
        where T : new()
    {
        var ret = (IInterface)new T();
        ret.X = a.X + b.X;
        ret.Y = a.Y + b.Y;
        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<Foo>(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<Bar>(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();
    }
}

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

If your interfaces contained more than just contracts that would be violating design by contract.

这篇关于为C#接口定义隐式和显式转换的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆