2010-06-18 13 views
5

Digamos que he 2 interfaces definidas así:herencia de varios niveles con implementos en características en VB.NET vs C#

public interface ISkuItem 
{ 
    public string SKU { get; set; } 
} 

public interface ICartItem : ISkuItem 
{ 
    public int Quantity { get; set; } 
    public bool IsDiscountable { get; set; } 
} 

Cuando voy a implementar la interfaz en C#, VS produce el siguiente código de plantilla :

public class CartItem : ICartItem 
{ 

    #region ICartItem Members 

    public int Quantity { get {...} set {...} } 

    public bool IsDiscountable { get {...} set {...} } 

    #endregion 

    #region ISkuItem Members 

    public string SKU { get {...} set {...} } 

    #endregion 
} 

En VB.NET, la misma clase se construye de esta manera:

Public Class CartItem 
    Implements ICartItem 

    Public Property IsDiscountable As Boolean Implements ICartItem.IsDiscountable 
     'GET SET' 
    End Property 

    Public Property Quantity As Integer Implements ICartItem.Quantity 
     'GET SET' 
    End Property 

    Public Property SKU As String Implements ISkuItem.SKU 
     'GET SET' 
    End Property 
End Class 

VB.NET explícitamente requiere que agregue Implements IInterfaceName.PropertyName después de cada propiedad que se implementa, mientras que C# simplemente usa region para indicar qué propiedades y métodos pertenecen a la interfaz.

Curiosamente en VB.NET, en la propiedad SKU, puedo especificar Implements ISkuItem.SKU o Implements ICartItem.SKU. Aunque la plantilla creada por VS tiene como valor predeterminado ISkuItem, también puedo especificar ICartItem si así lo deseo. Curiosamente, como C# solo usa region para bloquear las propiedades heredadas, parece que no puedo especificar explícitamente la interfaz de implementación de SKU en C# como puedo en VB.NET.

Mi pregunta es: ¿Hay alguna importancia detrás de poder especificar una interfaz u otra para implementar propiedades en VB.NET, y si es así, hay una manera de imitar esta funcionalidad en C#? Además, ¿cuál es el efecto de especificar una interfaz sobre otra cuando se implementan propiedades?

Respuesta

8

creo que las otras respuestas en realidad están un poco fuera de lugar aquí.

En el ejemplo que ha publicado, una interfaz hereda del otro. Esto simplemente significa que ofrece los mismos miembros que su base, más algunos miembros adicionales.

Estas no son dos interfaces independientes que exponen miembros con el mismo nombre. ICartItem.SKUes lo mismo queISkuItem.SKU. Que ICartItem hereda de ISkuItem simplemente significa que ISkuItem, como una interfaz, representa un subconjunto de la funcionalidad ofrecida por ICartItem.

consideran este código:

class CartItem : ICartItem 
{ 
    public int Quantity { get; set; } 
    public bool IsDiscountable { get; set; } 

    string ISkuItem.SKU 
    { 
     get { return "ISkuItem"; } 
     set { throw new NotSupportedException(); } 
    } 

    string ICartItem.SKU 
    { 
     get { return "ICartItem"; } 
     set { throw new NotSupportedException(); } 
    } 
} 

Esta clase no se compilará. No se puede definir ICartItem.SKU explícitamente en este caso, porque ICartItem.SKU es solo ISkuItem.SKU. No hay ninguna "otra" propiedad SKU para definir.

Por lo tanto, para responder a sus preguntas directamente:

¿Hay alguna importancia detrás de ser capaz de especificar una interfaz o otra para poner en práctica properites en VB.NET?

Cuando están separados, las interfaces no relacionadas: .
Como han señalado otros, puede proporcionar diferentes implementaciones para miembros de diferentes interfaces que comparten un nombre común.

Pero cuando una interfaz hereda de la otra: sin.
No importa porque son lo mismo.

¿Cuál es el efecto de especificar una interfaz de sobre otra cuando properites ejecución?

Nuevamente, si son interfaces no relacionadas, tiene el efecto ya discutido por otros: proporcionar diferentes implementaciones para las dos interfaces. Pero si uno deriva del otro, no tiene efecto.

+0

Este es un punto diferente. El contrato 'ICartItem.SKU' no se puede explicitar porque no forma parte explícita de' ICartItem' –

+0

@Matthew: Bueno, podrías verlo de esa manera también; mi punto es que estos no son dos miembros diferentes, como lo serían si las interfaces no estuvieran relacionadas. Creo que el hecho de que en VB.NET pueda especificar 'Implements ISkuItem.SKU' ** o **' Implements ICartItem.SKU' hace que esto sea un poco más claro también. –

+0

BTW ... si crea una instancia de 'CartItem' no podrá acceder a la propiedad' SKU' a menos que lo ladee en la interrelación de 'ISkuItem' (suponiendo que agregue' SKU' a 'ICartItem' así que ejemplo compilará.) –

2

Sí, esto es importante, esto se llama implementación de interfaz Explicit and Implicit.

En C# se puede hacer esto con el prefijo nombre del método con un nombre de interfaz, así:

public class CartItem : ICartItem, ISkuItem 
{ 

    #region ICartItem Members 

    public int Quantity { get {...} set {...} } 

    public bool IsDiscountable { get {...} set {...} } 

    #endregion 

    #region ISkuItem Members 

    public string ISkuItem.SKU { get {...} set {...} } //like this 
    public string ICartItem.SKU { get {...} set {...} } //like this 

    #endregion 
} 
+0

Esto es cierto e informativo, pero en el caso del OP una interfaz hereda de la otra, lo que cambia las cosas. Este código que ha publicado, basado en las definiciones de OP de las dos interfaces, no se compilará. –

+0

Lo siento, simplemente olvidé agregar ISkuItem, actualizado. – Restuta

+0

Sin embargo, ese no era el problema; si 'CartItem' implementa' ICartItem', entonces también implementa 'ISkuItem' ya sea que escriba': ISkuItem' junto a la declaración de clase o no. Mi punto es que 'ISkuItem.SKU' y' ICartItem.SKU' son lo mismo, por lo que no puedes definirlos (realmente: "eso") dos veces en la misma clase. –

2

Sí, se puede implementar una funcionalidad diferente detrás de cada interfaz. Supongamos que ambas interfaces tienen la misma firma. Dependiendo de la interfaz a la que transfiera su implementación, se controlará qué interfaz se ejecuta.

... C# Ejemplo de interfaces explict ...

public interface ITest1 { string Get(); } 
public interface ITest2 { string Get(); } 
// new is just to get rid of a compiler warning 
public interface ITest3 : ITest1, ITest2 { new string Get(); } 
public class MyTest : ITest1, ITest2 
{ 
    public string Get() { return "local"; } 
    string ITest1.Get() { return "hello"; } 
    string ITest2.Get() { return "world"; } 
    string ITest3.Get() { return "hi"; } 
} 
class Program 
{ 
    static void Main(string[] args) 
    { 
     var mytest = new MyTest(); 
     // note that if mytest.Get() does not exist if all of the 
     // interfaces are explicit 
     var v0 = mytest.Get(); //local 
     var v1 = ((ITest1)mytest).Get(); //hello 
     var v2 = ((ITest2)mytest).Get(); //world 
     var v3 = ((ITest3)mytest).Get(); //hi 
    } 
} 

... Código similares en VB.Net ...

Module Module1 

    Sub Main() 
     Dim myinstance = New MyTest() 
     Dim v0 = myinstance.DoWork() 'local 
     'By the way... note that the following methods are called 
     'by the interface signature and not the defind method name 
     'in the class 
     Dim v1 = DirectCast(myinstance, ITest1).DoWork() 'hello 
     Dim v2 = DirectCast(myinstance, ITest2).DoWork() 'world 
     Dim v3 = DirectCast(myinstance, ITest3).DoWork() 'hi 
    End Sub 

End Module 

Public Interface ITest1 
    Function DoWork() As String 
End Interface 
Public Interface ITest2 
    Function DoWork() As String 
End Interface 
Public Interface ITest3 
    Inherits ITest1 
    Inherits ITest2 

    Shadows Function DoWork() As String 
End Interface 
Public Class MyTest 
    Implements ITest3 
    'Implements ITest1 
    'Implements ITest2 

    Public Function DoWork() As String 
     Return "local" 
    End Function 

    Private Function DoWork1() As String Implements ITest1.DoWork 
     Return "hello" 
    End Function 

    Private Function DoWork2() As String Implements ITest2.DoWork 
     Return "world" 
    End Function 

    Private Function DoWork3() As String Implements ITest3.DoWork 
     Return "hi" 
    End Function 
End Class 
+0

Esto es cierto e informativo, pero en el caso del OP una interfaz hereda de la otra, lo que cambia las cosas. –

+0

Jaja, ahora acabas de hacer un monstruo. ¿Por qué definir una interfaz que hereda de dos interfaces con un solo miembro en conflicto? Esto parece casi insignificante para mí, a menos que su único propósito para definirlo de esta manera sea tener una interfaz que esencialmente garantice que se puede transmitir a una de las dos * otras * interfaces. Pero entonces, ¿por qué el miembro 'new' /' Shadows'? Pura locura. No lo toleraré. –

+0

@Dan, lol ... No estoy realmente preocupado si lo soportarías. Mi punto era más para mostrar lo que sucede. Además, las nuevas/sombras no son necesarias ... pero si no te agradan las advertencias del compilador serían necesarias. –

Cuestiones relacionadas