有没有办法模仿类中共享方法的接口/契约以供泛型使用? [英] Is there a way to mimic an interface/contract for shared methods in a class for use by generics?

查看:29
本文介绍了有没有办法模仿类中共享方法的接口/契约以供泛型使用?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

所以我实现了自己的 Enum 静态类形式,以便我可以将字符串与枚举值相关联.每个枚举类中的一个共享函数 GetValue 用于通过偏移量从内部数组中快速查找字符串值.虽然所有枚举类都实现了完全相同的函数,但它们的参数数据类型不同,具体取决于每个类中的枚举.

So I implemented my own form of Enum static classes so I can associate strings to enumeration values. One of the shared functions in each enum class, GetValue, is used to quickly look up the string value from an internal array via the offset. While all of the enum classes implement the same exact function, the data types of their parameters differ, specific to the enums in each class.

所以我想创建一个泛型类,该类可以通过将任何枚举作为泛型类型参数传递来使用它.但是我找不到一种方法来约束类型 T 以能够调用每个枚举的 GetValue 函数.这是接口可以派上用场的地方,但 VB.NET 禁止共享方法的接口.

So I come to a point where I want to create a generic class that can use any of the enums by passing it as a generic type parameter. But I cannot find a way to constrain type T in such a way to be able to call each enum's GetValue function. This is where an interface would come in handy, but VB.NET forbids interfaces for shared methods.

我有一个可以约束的基类,但是基类没有实现 GetValue 方法,我无法定义它的通用版本,因为我需要依赖在每个子类的共享属性上,以便 GetValue 做它的事情.

I have a base class that I could constrain to, but the base class doesn't implement the GetValue method, and I can't define a generic version of it, because I need to rely on shared properties of each child class in order for GetValue to do its thing.

还有其他方法可以解决这个问题吗?

Is there another way to tackle this?


下面是一个示例枚举类的样子.父级 EBase 没有什么特别的,只是托管常见的 NameValueType 属性,以及两个共享的运算符,op_Equalityop_Inequality.想象一下,将几个枚举类与一个泛型方法(或类)一起使用,并且需要通过泛型类型参数 T 访问 GetValue 成员.


Here's what an example enum class looks like. The parent, EBase is nothing special, just hosting common Name, Value, and Type properties, plus two shared operators, op_Equality and op_Inequality. Imagine using a couple of these enum classes with a generic method (or class) and needing to access the GetValue member via the generic type parameter T.

Friend NotInheritable Class EExample
    Inherits EBase

    Private Sub New()
    End Sub


    Friend Shared Function GetValue(ByVal Name As String) As Enums
        Return Enums(Array.IndexOf(_Names, Name))
    End Function


    'Num of Enums defined.
    Friend Shared ReadOnly MaxEnums As Int32 = 5

    'String literals.
    Private Shared ReadOnly _Names As String() = New String() _
        {"one_adam", "two_boy", "three_charles", "four_david", "five_edward"}

    'Enums.
    Friend Shared ReadOnly OneA As New Enums(_Names(0), 0)
    Friend Shared ReadOnly TwoB As New Enums(_Names(1), 1)
    Friend Shared ReadOnly ThreeC As New Enums(_Names(2), 2)
    Friend Shared ReadOnly FourD As New Enums(_Names(3), 3)
    Friend Shared ReadOnly FiveE As New Enums(_Names(4), 4)


    'Enum Values Array.
    Friend Shared ReadOnly Values As Enums() = New Enums() _
        {OneA, TwoB, ThreeC, FourD, FiveE}


    Friend NotInheritable Class Enums
        Inherits EBase

        Private Sub New()
        End Sub

        Friend Sub New(ByVal Name As String, ByVal Value As Int32)
            MyBase.Name = Name
            MyBase.Value = Value
            MyBase.Type = GetType(Enums)
        End Sub
    End Class
End Class

以下是这些东西的使用方法:

Here's how the things are used:

Dim Foo As EExample.Enums
Foo = EExample.TwoB
Debug.Print(Foo.Name)

将打印two_boy

推荐答案

如何解决这个问题:

Friend NotInheritable Class EExample
    Inherits EBase

    Protected Sub New()
    End Sub

    Protected Overrides Function BuildValues() As EBase.Enums()
        Return New Enums() _
        { _
            Build(Of EExample)("one_adam", 0), _
            Build(Of EExample)("two_boy", 1), _
            Build(Of EExample)("three_charles", 2), _
            Build(Of EExample)("four_david", 3), _
            Build(Of EExample)("five_edward", 4) _
        }
    End Function

    Private Shared _instance As EExample = New EExample()

    Friend Shared ReadOnly OneA As Enums = _instance.Values(0)
    Friend Shared ReadOnly TwoB As Enums = _instance.Values(1)
    Friend Shared ReadOnly ThreeC As Enums = _instance.Values(2)
    Friend Shared ReadOnly FourD As Enums = _instance.Values(3)
    Friend Shared ReadOnly FiveE As Enums = _instance.Values(4)

End Class

EBase 然后看起来像这样:

Public MustInherit Class EBase

    Protected MustOverride Function BuildValues() As Enums()

    Private _values As EBase.Enums()

    Friend ReadOnly Property Values() As EBase.Enums()
        Get
            If _values Is Nothing Then
                _values = Me.BuildValues()
            End If
            Return _values
        End Get
    End Property

    Friend ReadOnly MaxAlterEnums As Int32 = Me.Values.Length

    Friend Function GetValue(ByVal Name As String) As Enums
        Return Me.Values.Where(Function(n) n.Name = Name).FirstOrDefault()
    End Function

    Friend Shared Function Build(Of T As EBase)(ByVal name As String, ByVal value As Int32) As Enums
        Return New Enums(name, value, GetType(T))
    End Function

    Public Class Enums
        Public Sub New(ByVal name As String, ByVal value As Int32, ByVal type As Type)
            Me.Name = name
            Me.Value = value
            Me.Type = type
        End Sub
        Private _name As String
        Public Property Name() As String
            Get
                Return _name
            End Get
            Set(ByVal Value As String)
                _name = Value
            End Set
        End Property
        Private _value As Integer
        Public Property Value() As Integer
            Get
                Return _value
            End Get
            Set(ByVal Value As Integer)
                _value = Value
            End Set
        End Property
        Private _type As Type
        Public Property Type() As Type
            Get
                Return _type
            End Get
            Set(ByVal Value As Type)
                _type = Value
            End Set
        End Property
    End Class

End Class

现在您的示例代码与以前完全一样:

Now your sample code works exactly as before:

    Dim Foo As EExample.Enums
    Foo = EExample.TwoB
    Debug.Print(Foo.Name)

并且您正在处理代码实现的普通实例.唯一的 Shared 值是五个 Enums 和一个私有的 _instance 变量.

And you are dealing with plain instances for you code implementation. The only Shared values are the five Enums and a private _instance variable.

您现在可以限制 EBase.

这对你有用吗?

Kumba 指出我没有在 EExample 类上公开 GetValue 函数.

Kumba pointed out that I didn't expose the GetValue function on the EExample class.

只需将其添加到EExample:

    Friend Shared Function GetValue(ByVal Name As String) As Enums
        Return _instance.GetValue(Name)
    End Function

这篇关于有没有办法模仿类中共享方法的接口/契约以供泛型使用?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆