Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Defining implicit and explicit casts for C# interfaces

Tags:

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; }
     }
 }

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};
     }
 }

And the interface...

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

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?)

like image 388
ehdv Avatar asked May 05 '10 19:05

ehdv


People also ask

What do you mean by implicit type casting in C?

Implicit Type Conversion is also known as 'automatic type conversion'. It is done by the compiler on its own, without any external trigger from the user. It generally takes place when in an expression more than one data type is present.

Does C have implicit conversion?

Implicit type conversion in C language is the conversion of one data type into another datatype by the compiler during the execution of the program. It is also called automatic type conversion.

What is explicit data type casting?

A cast, or explicit type conversion, is special programming instuction which specifies what data type to treat a variable as (or an intermediate calculation result) in a given expression. Casting will ignore extra information (but never adds information to the type being casted).


2 Answers

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.

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.

like image 118
cfeduke Avatar answered Nov 22 '22 05:11

cfeduke


One way to do this is if there is a cast/conversion you'll often need is to define an explicit method on your interface e.g.

public interface ISomeInterface
{
   TargetType ToTargetType();
}

Then in an abstract base class you can define an implicit/explicit cast and have the cast operator just call the interface method in which you define your actual cast logic e.g.

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

  public static explicit operator TargetType(SomeAbstractClass obj)
  {
    return ToTargetType();
  }
}

This way you ensure that implementations provide a means to cast to the necessary type. Thus purely interface driven code can call the interface method to do the conversion. But your code that uses concrete implementations of the interface will have the cast operators defined and can use them instead

like image 25
RobV Avatar answered Nov 22 '22 04:11

RobV