VB .Net довольно сложная ситуация, но много информации предоставлено - PullRequest
1 голос
/ 17 февраля 2012

Я создал класс, который наследует List(Of TKey, TValue) и добавляет несколько функций. Его цель - не добавлять элементы во время выполнения, но когда он инициализируется. Я на самом деле хотел бы удалить методы добавления / удаления из класса (так как он в настоящее время предоставляет их из унаследованного класса).

Если вы увидите класс TestApp, то увидите, если я добавлю List(Of String, Integer) к классу, он работает просто отлично. Однако в приведенном ниже коде, когда я пытаюсь использовать Me.Add() в конструкторе класса; добавить это не работает. Это фактически говорит мне, что String не может быть преобразован в TKey, а Integer не может быть преобразован в TValue. Что не соответствует действительности! Он отлично работает в тестовом приложении.

Есть идеи? Вот код Два класса, класс Vars и приложение Test.

Примечание. Даже при использовании метода переопределения Add из класса, так как Me.Add(String, Integer) не работает (та же ошибка)

Imports System
Imports System.Collections.Generic
Imports System.Text


Public Class Vars(Of TKey, TValue)

Inherits List(Of KeyValuePair(Of TKey, TValue))

''' <summary>
'''     Initializes the class and fills with Key->Value Pairs
''' </summary>
''' <remarks>
'''     This does not work when adding directly from the class. When I overload
''' the Add() function, and call it with a KeyValuePair(Of String, String) in a
''' class instance it works, see below
''' </remarks>
Public Sub New()
    Dim kv = New KeyValuePair(Of TKey, TValue)("This", 1)
    Me.Add(kv)
End Sub

''' <summary>
'''     Adds an item to the class by String, Integer
''' </summary>
''' <param name="aKey">A String containing the Key of the element to be added.</param>
''' <param name="aValue">An Integer containing the Value of the element to be added.</param>
''' <remarks>
'''     This Works fine when called as in the demo shown below.
''' </remarks>
Public Overloads Sub Add(ByVal aKey As TKey, ByVal aValue As TValue)
    Dim kv = New KeyValuePair(Of TKey, TValue)(aKey, aValue)
    Me.Add(kv)
End Sub

''' <summary>
'''     Finds a Value stored in the class based on a given Key.
''' </summary>
''' <param name="key">A String containing a Key to search for.</param>
''' <remarks>Works.</remarks>
Public Function FindByKey(ByVal key As TKey) As List(Of KeyValuePair(Of TKey, TValue))
    Return Me.FindAll(Function(item As KeyValuePair(Of TKey, TValue)) (item.Key.Equals(key)))
End Function

''' <summary>
'''     Finds a Key stored in the class based on a given Value.
''' </summary>
''' <param name="value">An Integer containing the Value to search for.</param>
''' <remarks>Works</remarks>
Public Function FindByValue(ByVal value As TValue) As List(Of KeyValuePair(Of TKey, TValue))
    Return Me.FindAll(Function(item As KeyValuePair(Of TKey, TValue)) (item.Value.Equals(value)))
End Function

End Class

Public Class TestApp
    Shared Sub Main()
        Dim varTest As Vars(Of String, Integer) = New Vars(Of String, Integer)
        varTest.Add("Kung", 1)
        varTest.Add("Foo", 2)

        For Each var In varTest
            Console.WriteLine(var.Key & ":" & var.Value)
        Next

        'Output would be
        '
        '  Kung:1
        '  Foo:2
    End Sub
End Class

Ответы [ 2 ]

7 голосов
/ 17 февраля 2012

Здесь происходит множество вещей.

  1. В частности: Ваш класс предназначен для как универсальный? То есть вы собираетесь использовать Vars(Of String, Integer), Vars(Of Object, DateTime), Vars(Of Double, Object) и все виды? Если так, то что бы вы хотели, чтобы произошло в этой строке:

    Dim kv = New KeyValuePair(Of TKey, TValue)("This", 1)
    

    когда TKey равно не String, а TValue равно не Integer? единственное, что вы можете добавить к List(Of KeyValuePair(Of TKey, TValue)) это KeyValuePair(Of TKey, TValue), а не просто какой-то старый KeyValuePair.

  2. В более общем смысле: List(Of T) не предназначен для наследования с (это часто возникает, это только первый пример ответа Я нашел). Во что бы то ни стало ваш класс содержит a List(Of T) и хранит в нем предметы, но а не наследовать, вы должны точно решить, что вы хотите Публичный интерфейс вашего класса будет и реализовывать только это. Это может быть тем, что реализация IList или какого-либо другого предопределенного интерфейса дает вам нужный контракт, но не обязательно.

  3. Даже в более общем плане: когда вы обнаружите, что говорите: «Я бы на самом деле как удалить методы добавления / удаления из класса ", это массивный намек на то, что вы не должны наследовать от этого класса . Принцип подстановки Лискова говорит (примерно), что все, что наследует от класса C должен иметь возможность обрабатываться как C: если вы наследуете от List, вызывающие абоненты вполне ожидают быть в состоянии Add и Delete. Если вы не хотите, чтобы эти методы ваш публичный интерфейс, не наследуйте от этого класса.

0 голосов
/ 23 февраля 2012

Чтобы опираться на другой ответ здесь и включить предложение о том, как решить проблему, это классический случай, когда следует использовать композиция , а не наследование. Создайте тип, который оборачивает список как приватный член. Новый тип будет иметь только тот метод и свойства, которые вы хотите. Это будет легко реализовать, но несколько утомительно, поскольку каждый метод или свойство в новом типе просто вызовет соответствующий метод в оригинале.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...