c# - System.String 实现自定义接口
问题描述
我有一个Interface
定义了一组类,它们都实现了该.ToString
成员。我怎样才能使本机数据类型也String
实现这Interface
一点?
首先,我不确定无论如何我会怎么做,但有件事告诉我,这String
让NotInheritable
事情变得更加困难?
我的试探性如下:(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
解决方案
以下是解决您困境的两种替代策略:
不用为不同类型的字符串创建不同的类,只需创建一个具有两个字段的类(例如 SpecialString)——一个字符串和一个枚举值来描述它包含的字符串类型(例如 Normal、Base64 等)。然后,您可以将该类传递给需要能够接受这两种类型的字符串但仍然能够确定它是哪种类型的函数。您甚至可以编写
Widening Operator CType
从字符串到 SpecialString 的隐式转换(即),这样您甚至不需要为普通字符串显式创建 SpecialString。如果您想将不同类型的字符串保留为单独的类,您可以创建一个
AnyString
实现 ToString 的基类(例如)。然后创建Base64String
为派生自AnyString
. 您可以编写一个隐式转换运算符 fromSystem.String
toAnyString
。AnyString
如果您想同时接受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!
推荐阅读
- python - sys.stdin.readline 的问题
- c# - myItem.Id,这是跨系统唯一的吗
- android - 使用同一行中最大长度的文本更新 SQLite 列
- html - babylonjs 场景边框的小问题
- mysql - 数据仓库逻辑模型
- python - 不能使用带下标的赋值表达式
- python - 如何在 txt 文件中使用 pandas.DataFrame.to_csv 保存二维数组
- python - 在 Python 中操作列表中的一些值
- autohotkey - 为什么我的代码在最后打印双“k”?自动热键 (ahk)
- c# - 将光标移动到下一行,使其与上一行的最后一个字符对齐