Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Multi-level inheritance with Implements on properties in VB.NET vs C#

Let's say I have 2 interfaces defined like so:

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

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

When I go to implement the interface in C#, VS produces the following templated code:

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
}

In VB.NET, the same class is built out like so:

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 explicitly requires you to add Implements IInterfaceName.PropertyName after each property that gets implemented whereas C# simply uses regions to indicate which properties and methods belong to the interface.

Interestingly in VB.NET, on the SKU property, I can specify either Implements ISkuItem.SKU or Implements ICartItem.SKU. Although the template built by VS defaults to ISkuItem, I can also specify ICartItem if I want. Oddly, because C# only uses regions to block out inherited properties, it seems that I can't explicitly specify the implementing interface of SKU in C# like I can in VB.NET.

My question is: Is there any importance behind being able to specify one interface or another to implement properties in VB.NET, and if so, is there a way to mimic this functionality in C#? Furthermore, what is the effect of specifying one interface over another when implementing properties?

like image 954
Ben McCormack Avatar asked Jun 18 '10 14:06

Ben McCormack


2 Answers

I think the other answers are actually a little off the mark here.

In the example you've posted, one interface inherits from the other. This simply means that it offers the same members as its base, plus some additional members.

These are not two independent interfaces that happen to expose members with the same name. ICartItem.SKU is the same thing as ISkuItem.SKU. That ICartItem inherits from ISkuItem simply means that ISkuItem, as an interface, represents a subset of the functionality offered by ICartItem.

Consider this code:

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

This class will not compile. You cannot define ICartItem.SKU explicitly in this case, because ICartItem.SKU is just ISkuItem.SKU. There's no "other" SKU property to define.

So, to answer your questions directly:

Is there any importance behind being able to specify one interface or another to implement properites in VB.NET?

When they are separate, unrelated interfaces: yes.
As others have pointed out, you can provide different implementations for different interfaces' members sharing a common name.

But when one interface inherits from the other: no.
It doesn't matter because they're the same thing.

What is the effect of specifying one interface over another when implementing properites?

Again, if they're unrelated interfaces, it has the effect already discussed by others: providing different implementations for the two interfaces. But if one derives from the other, it has no effect.

like image 64
Dan Tao Avatar answered Oct 27 '22 22:10

Dan Tao


Yes, you can implement different functionality behind each interface. Assume both interfaces have the same signature. Depending on which interface you cast your implementation to will control which interface is executed.

... C# Example of explict interfaces ...

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

... Similar Code in 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
like image 41
Matthew Whited Avatar answered Oct 27 '22 23:10

Matthew Whited