Скажем, у меня есть 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#? Кроме того, каков эффект определения одного интерфейса по другому при реализации свойств?
Я думаю, что другие ответы здесь немного неуместны.
В опубликованном вами примере один интерфейс наследует от другого. Это просто означает, что он предлагает тех же участников, что и его база, плюс несколько дополнительных участников.
Это не два независимых интерфейса, которые могут открывать элементы с одинаковыми именами. 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.Артикул
- это просто ISkuItem.SKU
. Нет никакого "другого" свойства SKU
для определения.
Итак, отвечая прямо на ваши вопросы:
Есть ли какое-то значение за тем, чтобы быть возможность указать один интерфейс или другой для реализации свойств в VB.NET?
Когда они являются отдельными, несвязанными интерфейсами : да .
Как указывали другие, вы можете предоставить разные реализации для разных членов интерфейсов, имеющих общее имя.
Но когда один интерфейс наследуется от другого : нет .
Это не имеет значения, потому что это одно и то же.
Каков эффект от указания одного интерфейс над другим, когда реализация свойств?
Опять же, если они не связаны между собой интерфейсами, это имеет эффект, уже обсужденный другими: предоставление разных реализаций для двух интерфейсов. Но если одно происходит от другого, это не имеет никакого эффекта .
Да это важно, это называется Явная и неявная реализация интерфейса.
В 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
}
Да, вы можете реализовать различную функциональность за каждым интерфейсом. Предположим, что оба интерфейса имеют одинаковую сигнатуру. В зависимости от того, к какому интерфейсу вы приведете свою реализацию, будет зависеть, какой интерфейс будет выполняться.
... 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