visual valor tipos studio programacion pequeño para implicita grande demasiado datos conversion c# interface

valor - Definición de conversiones implícitas y explícitas para interfaces C#



tipos de datos en c# visual studio (2)

¿Hay una manera de escribir código basado en interfaz (es decir, usar interfaces en lugar de clases como los tipos aceptados y transmitidos) en C # sin renunciar al uso de elementos como los lanzamientos implícitos? Aquí hay un código de ejemplo: se ha eliminado mucho, pero estas son las partes relevantes.

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

Y en ScrDictionary.cs, tenemos ...

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

Y la interfaz ...

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

Quiero poder usar IScrDictionary lugar de ScrDictionary , pero igual puedo convertir implícitamente un ScrDictionary a Game.VariantInfo . Además, si bien puede haber una manera fácil de hacer que esto funcione, dándole a IScrDictionary una propiedad de tipo Game.VariantInfo mi pregunta es más general: ¿hay una manera de definir conversiones o la sobrecarga de operadores en las interfaces? (Si no es así, ¿cuál es la forma correcta de C # para mantener esta funcionalidad sin renunciar al diseño orientado a la interfaz?)


No puede definir conversiones o sobrecarga de operadores en las interfaces. Ya que una interfaz es un contrato que describe los miembros que siempre estarán disponibles (ya sea como una conversión explícita a esa interfaz o como miembros públicos) y nada más, no puede confiar en las interfaces para contener ningún tipo de lógica integrada, como la forma de la conversión o cómo operarán los operadores con esa interfaz.

Aún puede heredar de una clase base abstracta que implementa la interfaz y proporciona la lógica que necesita para las conversiones o la sobrecarga de operadores. Esto no viola el diseño orientado a la interfaz. Las clases que no heredan de la clase base común pero que implementan la interfaz todavía necesitarán implementar de forma independiente sus propios procesos implícitos y sobrecargas de operadores. Si desea centralizar la lógica para trabajar con clases que comúnmente implementan una interfaz, puede hacerlo en C # 3.0 + / .NET Fx 3.5 con métodos de extensión (o en versiones anteriores con métodos estáticos). A continuación, demuestro esto con una clase de utilidad y dos clases, Foo y Bar, que no tienen un ancestro común. Comparten el código que comprende la función de utilidad Agregar para que no tenga que repetir esta implementación en ambas clases.

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

Si sus interfaces contenían más que solo contratos que estarían violando el diseño por contrato.


Una forma de hacerlo es si hay una conversión / conversión que es probable que a menudo necesite definir como un método en su interfaz, por ejemplo:

public interface ISomeInterface { TargetType ToTargetType(); }

Luego, en una clase base abstracta, puede definir una conversión implícita / explícita y tener la implementación de ToTargetType() simplemente llame al operador de ToTargetType() , por ejemplo

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

De esta manera, se asegura de que las implementaciones proporcionen un medio para convertir al tipo necesario de modo que el código puramente dirigido por la interfaz pueda llamar al método de la interfaz para realizar la conversión. Pero su código que usa implementaciones concretas de esa interfaz que tienen los operadores de conversión definidos puede usarlas en su lugar