Многоуровневое наследование с Реализациями свойств в VB.NET против C # - PullRequest
5 голосов
/ 18 июня 2010

Допустим, у меня есть 2 интерфейса, определенных так:

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

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

Когда я иду для реализации интерфейса в C #, VS производит следующий шаблонный код:

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
}

В VB.NET тот же класс построен так:

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 явно требует, чтобы вы добавляли Implements IInterfaceName.PropertyName после каждого реализуемого свойства, тогда как C # просто использует region s, чтобы указать, какие свойства и методы принадлежат интерфейсу.

Интересно, что в VB.NET в свойстве SKU я могу указать либо Implements ISkuItem.SKU, либо Implements ICartItem.SKU. Хотя шаблон, созданный VS, по умолчанию ISkuItem, я также могу указать ICartItem, если захочу. Как ни странно, поскольку C # использует только region s для блокировки унаследованных свойств, кажется, что я не могу явно указать интерфейс реализации SKU в C #, как я могу в VB.NET.

У меня такой вопрос: Есть ли какая-то важность в возможности указать тот или иной интерфейс для реализации свойств в VB.NET, и если да, то есть ли способ имитировать эту функциональность в C #? Кроме того, каково влияние указания одного интерфейса на другой при реализации свойств?

Ответы [ 3 ]

8 голосов
/ 18 июня 2010

Я думаю, что другие ответы на самом деле немного неуместны.

В приведенном вами примере один интерфейс наследует от другого.Это просто означает, что он предлагает те же элементы, что и его база, а также некоторые дополнительные элементы.

Это не два независимых интерфейса, которые предоставляют элементы с одинаковым именем.ICartItem.SKU - это то же самое, что и ISkuItem.SKU.То, что ICartItem наследуется от ISkuItem, просто означает, что ISkuItem как интерфейс представляет собой подмножество функций, предлагаемых ICartItem.

Рассмотрим этот код:

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

Этот класс не будет компилироваться .Вы не можете определить ICartItem.SKU явно в этом случае, потому что ICartItem.SKU это просто ISkuItem.SKU.Нет никакого «другого» * ​​1027 * свойства для определения.

Итак, чтобы ответить на ваши вопросы напрямую:

Есть ли какая-либо важность для возможности указать тот или иной интерфейс для реализациисвойства в VB.NET?

Когда они являются отдельными, не связанными интерфейсами : да .
Как указали другие, вы можете предоставить различныереализации для членов различных интерфейсов, имеющих общее имя.

Но когда один интерфейс наследует от другого : нет .
Это не имеет значения, потому что ониэто то же самое.

Каково влияние указания одного интерфейса на другой при реализации свойств?

Опять же, если они не связаны между собой, он имеетэффект уже обсуждался другими: предоставление различных реализаций для двух интерфейсов.Но , если одно происходит от другого, это не имеет никакого эффекта .

2 голосов
/ 18 июня 2010

Да, вы можете реализовать различные функции за каждым интерфейсом. Предположим, что оба интерфейса имеют одинаковую подпись. В зависимости от того, к какому интерфейсу вы привели свою реализацию, будет контролироваться, какой интерфейс выполняется.

... C # Пример эксплицитных интерфейсов ...

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

... Аналогичный код в 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
2 голосов
/ 18 июня 2010

Да, это важно, это называется Явная и неявная реализация интерфейса.

В C # вы можете сделать это, добавив префикс имени метода к имени интерфейса, например:

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
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...