views:

93

answers:

3

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

+2  A: 

Yes this is importance, this called Explicit and Implicit interface implementation.

In C# you can do this by prefixing method name with an interface name, like that:

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
}
Restuta
This is true and informative, but in the OP's case one interface inherits from the other, which changes things. This code you've posted, based on the OP's definitions of the two interfaces, won't compile.
Dan Tao
Sorry, just forgot to add ISkuItem, updated.
Restuta
@Restuta: That wasn't the issue, though; if `CartItem` implements `ICartItem`, then it also implements `ISkuItem` whether or not you write `: ISkuItem` next to the class declaration. My point is that `ISkuItem.SKU` and `ICartItem.SKU` are the same thing, so you cannot define them (really: "it") twice in the same class.
Dan Tao
Yes I know, but I just want to illustrate difference for you.
Restuta
+2  A: 

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
Matthew Whited
This is true and informative, but in the OP's case one interface inherits from the other, which changes things.
Dan Tao
Haha, now you've just made a monster. Why define an interface that inherits from two interfaces with a single conflicting member? This seems almost meaningless to me, unless your sole purpose for defining it this way would be to have an interface that essentially guarantees it can be cast to one of two *other* interfaces. But then, why the `new`/`Shadows` member? Sheer insanity. I won't stand for it.
Dan Tao
@Dan, lol... I'm not really worried if you would stand for it. My point was more to show what happens. Also the new/Shadows are not required... but if you dislike compiler warnings they would be needed.
Matthew Whited
VB comments really don't play well on this site.
Matthew Whited
@Matthew: My question was more, "Why would you define a `DoWork` member on your `ITest3` interface at all?" Like, you have these two interfaces each having a method with the same name as the other. Then you introduce this third interface which *can't possibly offer the functionality of both* (due to the conflicting name), and yet it inherits from both. *Furthermore*, it defines an entirely new member with the same name yet again. So I deem this a wolf dressed in inheritance's clothing. `ITest3` really doesn't inherit from either `ITest1` or `ITest2` at all, in any conventional sense.
Dan Tao
@Dan, Methods are probably a bad example. But I have found uses for properties. Say you want a different setter interface defined from the getter. Then you could use a public factory to create an object, but treat that object as immutable after construction and have this be enforced by your interface contracts.
Matthew Whited
+6  A: 

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.

Dan Tao
This is a different point. The contract `ICartItem.SKU` can not be explict because it is not explictly part of `ICartItem`
Matthew Whited
@Matthew: Well, you could look at it that way too; my point is just that these are not two different members, as they would be if the interfaces were unrelated. I think the fact that in VB.NET you can specify `Implements ISkuItem.SKU` **or** `Implements ICartItem.SKU` makes this a bit clearer as well.
Dan Tao
BTW... if you create an instance of `CartItem` you will not be able to access the `SKU` property unless you cast it to the intereface of `ISkuItem` (assuming you add `SKU` to `ICartItem` so this example will compile.)
Matthew Whited
@Matthew: Yes, you and I both know that's the idea behind implementing an interface explicitly. But it seems like you're still missing my point. **`ISkuItem.SKU` is the same thing as `ICartItem.SKU`**. So you could cast a `CartItem` to an `ISkuItem` **or** an `ICartItem` and the `ISkuItem.SKU` property would be the same either way.
Dan Tao
VB.Net works the same as C# in this respect. You could not use `Implements ICartItem.SKU` because it's not defined
Matthew Whited
wow... VB is even more annoying then just more code. it would require multiple methods that would be explosed from the instance class that do not match the method names from the interface signature. (yet another reason I'm glad I moved to C#)
Matthew Whited
@Dan I read your StackOverflow bio. I was also a philosophy major in college :-)/
Ben McCormack
@Matthew: That's not true. It **is** defined because `ICartItem` inherits from `ISkuItem`. The VB.NET compiler will let you write it out either way. Try it for yourself.
Dan Tao
@Ben McCormack: Nice!
Dan Tao
@Dan, you have single inheritance interface. Mine has a diamond pattern issue because I have two conflicting child interfaces. But these are still different concepts. the VB.Net version will even allow you to rename the implmentation in the instances (which could be seen as good or bad.)
Matthew Whited
@Matthew: Yes, these are different concepts; but the OP's question deals with a single-inheritance scenario. I'm not sure why we would even want to *talk* about your diamond pattern issue: that's just confusing!
Dan Tao