我有一个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
我的一个潜艇应该能够接受几种Types作为输入,其中之一就是本机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
答案 0 :(得分:3)
这里有两种解决您困境的策略:
代替创建用于不同类型字符串的不同类,只需创建一个具有两个字段的单个类(例如SpecialString)-一个字符串和一个枚举值来描述其包含的字符串类型(例如Normal,Base64等)。然后,您可以将该类传递给需要能够接受两种类型的字符串但仍能够确定其为哪种类型的函数。您甚至可以编写从字符串到SpecialString的隐式转换(即Widening Operator CType
),这样您甚至无需为普通字符串显式创建SpecialString。
如果要将不同类型的字符串保留为单独的类,则可以创建实现ToString的基类(例如AnyString
)。然后将Base64String
创建为从AnyString
派生的类。您可以编写从System.String
到AnyString
的隐式转换运算符。如果要同时接受AnyString
和String
,则编写函数以接受Base64String
。或者,如果您想禁止普通的Base64String
,则可以只接受String
。
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
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!
答案 1 :(得分:2)
查看是否可行:
按如下方式重载DoSomething:
Sub DoSomething(MyData as String)
'... Do something using MyData string, for example send it to a WebAPI
End Sub
Sub DoSomething(MyData as IString)
DoSomething(MyData.ToString())
End Sub
使用本地字符串调用DoSomething时,将调用第一个方法。当您使用IString类型的对象调用DoSomething时,将调用第二个方法,该方法在内部以IString.ToString()值作为参数调用第一个DoSomething方法
答案 2 :(得分:0)
在C#中
否,您无法修改.ToString()
函数的行为。
您可以做的一件事就是使用扩展方法。但不幸的是,仅在没有适用的候选方法匹配时才检查扩展方法。在调用ToString()
的情况下,将始终有一个适用的候选方法,即object
上的ToString()。扩展方法的目的是扩展类型上可用的方法集,而不是覆盖现有方法。这就是为什么它们被称为“扩展方法”的原因。如果要覆盖现有方法,则必须制作一个覆盖方法。因此,您不应该为扩展方法使用名称ToString
,因为它永远不会被调用,因为该方法已经存在,并且您不应该使用T
,因为那里没有用。
这里是如何在C#中编写扩展方法的方法
public static class ListHelper
{
public static string ToMyString<T>(this IList<String> list)
{
return string.Join(", ", list.ToArray());
}
public static string ToMyString<T>(this String[] array)
{
return string.Join(", ", array);
}
}
已更新
您不能在第三方类上实现自定义接口。