首页 > 解决方案 > System.String 实现自定义接口

问题描述

我有一个Interface定义了一组类,它们都实现了该.ToString成员。我怎样才能使本机数据类型也String实现这Interface一点?

首先,我不确定无论如何我会怎么做,但有件事告诉我,这StringNotInheritable事情变得更加困难?

我的试探性如下:(C# 中的答案也是可以接受的)

Public Interface IString
    Function ToString() As String
End Interface

Partial Public Class String
    Implements IString

    Public Shadows Function ToString() As String Implements IString.ToString
        Return MyBase.ToString()
    End Function

End Class

我想要达到的目标

我的一个潜艇应该能够将几种类型作为输入,其中一种是本机String类型。

Sub DoSomething(MyData as IString)
    '... Do something using MyData.ToString, for example send it to a WebAPI
End Sub

Public Class SomeData
    Implements IString 'Sub DoSomething should accept this type
    Public Sub ToString() as String
        Return 'Something
    End Sub
End Class

Public Class SomeOtherData
    'Sub DoSomething should NOT accept this type
    Public Sub ToString() as String
        Return 'Something
    End Sub
End Class

我想避免这样做:

Sub DoSomething(MyData as Object)
    If not TypeOf MyData Is String or not TypeOf MyData Is SomeData Then Throw New ArgumentException()
    '...
End Sub

我想避免这样做:

Sub DoSomething(MyData as String)
    '...
End Sub

'Overload
Sub DoSomething(MyData as SomeData)
    call DoSomething(MyData.ToString)
End Sub

标签: c#.netvb.net

解决方案


以下是解决您困境的两种替代策略:

  1. 不用为不同类型的字符串创建不同的类,只需创建一个具有两个字段的类(例如 SpecialString)——一个字符串和一个枚举值来描述它包含的字符串类型(例如 Normal、Base64 等)。然后,您可以将该类传递给需要能够接受这两种类型的字符串但仍然能够确定它是哪种类型的函数。您甚至可以编写Widening Operator CType从字符串到 SpecialString 的隐式转换(即),这样您甚至不需要为普通字符串显式创建 SpecialString。

  2. 如果您想将不同类型的字符串保留为单独的类,您可以创建一个AnyString实现 ToString 的基类(例如)。然后创建Base64String为派生自AnyString. 您可以编写一个隐式转换运算符 from System.Stringto AnyStringAnyString如果您想同时接受String和 ,请编写要接受的函数Base64String。或者,Base64String如果您想禁止正常String的 s,您可以只接受 a。

策略 1 的示例代码:

Module Module1
    Enum StringType
        Normal
        Base64
        Base64DotBase64
    End Enum

    Class SpecialString
        Private type As StringType
        Private str As String

        Public Sub New(s As String, Optional type As StringType = StringType.Normal)
            Me.str = s
            Me.type = type
        End Sub

        Shared Widening Operator CType(ByVal s As String) As SpecialString
            Return New SpecialString(s, StringType.Normal)
        End Operator

        Public Overrides Function ToString() As String
            Return str
        End Function

        Public Function GetStringType() As StringType
            Return type
        End Function
    End Class

    'Function that uses SpecialString
    Sub Test(ss As SpecialString)
        ' Print StringType and inner value of string
        Console.WriteLine( ss.GetStringType().ToString("F") & ": " & ss.ToString())
    End Sub

    Sub Main()
        Dim ss1 As new SpecialString("abcdef", StringType.Base64)
        Dim ss2 As new SpecialString("abcdef:abcdef", StringType.Base64DotBase64)

        Test("Hello") 'Call with string
        Test(ss1) 'Call with Base64
        Test(ss2) 'Call with Base64DotBase64

        ' Pause to see the screen
        Console.ReadKey()
    End Sub

End Module

预期输出:

Normal: Hello 
Base64: abcdef 
Base64DotBase64: abcdef:abcdef

策略 2 的示例代码:

Imports System.Text.Encoding

Module Module1
    'Abstract base class to represent all string types (Normal and Base64 etc)
    MustInherit Class AnyString
        Private str As String
        Public Sub New(s As String)
            Me.str = s
        End Sub
        Public Overrides Function ToString() As String
            Return str
        End Function
        ' Allow implicit conversion of a System.String to NormalString, which inherits from AnyString
        Shared Widening Operator CType(ByVal s As String) As AnyString
            Return New NormalString(s)
        End Operator
    End Class

    'Class for Base64 strings only.
    Class Base64String
        Inherits AnyString
        Public Sub New(s As String)
            MyBase.New(s)
        End Sub
    End Class
    'Class for Normal strings. System.String implicitly converts to this.
    Class NormalString
        Inherits AnyString
        Public Sub New(s As String)
            MyBase.New(s)
        End Sub
        ' Allow implicit conversion of a System.String to NormalString
        ' This CType Operator isn't strictly necessary for this example, 
        ' because the CType in AnyString does the implict conversion shown below, 
        ' but it might be useful in general.
        Shared Widening Operator CType(ByVal s As String) As NormalString
            Return New NormalString(s)
        End Operator
    End Class

    'Function that Accepts Base64String OR Normal String
    Sub TestAny(s As AnyString)
        'Call ToString for whatever type of string was passed.
        Console.WriteLine(s.GetType().Name.ToString()  & ": " & s.ToString())

        'Also do something special for base64 string
        If TypeOf s Is Base64String then
            Console.WriteLine("Base64 Decoded (in TestAny): " & DecodeBase64(DirectCast(s,Base64String)))
        End If
    End Sub
    ' Function to convert Base64-encoded string to normal text. 
    ' This ONLY takes Base64Strings (not NormalStrings)
    Function DecodeBase64(s64 As Base64String) As String
        Return UTF8.GetString(System.Convert.FromBase64String(s64.ToString()))
    End Function

    Sub Main()
        'Normal String
        Dim s As new System.String("I am Normal")
        ' Base64String
        Dim s64 As New Base64String("SGVsbG8gV29ybGQh")

        'Call TestAny with any type of string
        TestAny("Hi") 'Call with string directly
        TestAny(s)    'Call with String object
        TestAny(s64)  'Call with Base64DotBase64

        'Call DecodeBase64 with a Base64String ONLY
        Console.Write("Base64-Decoded (in Main): ")
        Console.WriteLine(DecodeBase64(s64))   'OK call with Base64String
        'Console.WriteLine(DecodeBase64("Hi"))  !!! Invalid -- cannot call DecodeBase64 with string
        'Console.WriteLine(DecodeBase64(s))     !!! Invalid -- cannot call DecodeBase64 with string

        ' Pause to see the screen
        Console.ReadKey()
    End Sub

End Module

预期输出:

NormalString: Hi
NormalString: I am Normal
Base64String: SGVsbG8gV29ybGQh
Base64 Decoded (in TestAny): Hello World!
Base64-Decoded (in Main): Hello World!

推荐阅读