来自功能的Const

时间:2014-09-22 17:19:58

标签: vb.net

如何创建这样的功能? (框架如何为Chr做) 或者为什么不可能,但可能在框架中?

从函数声明的consts示例:

''' <summary>Carriage Return \r 13 0xD</summary>
Public Const Cr As Char = ChrW(&HD)
''' <summary>Line Feed \n 10 0xA</summary>
Public Const Lf As Char = ChrW(&HA)

MS reference source for ChrW

因此应该可以创建类似的函数ex:

Public Const Magic As String = "Magic" ' ok
Public Const lcMagic As String = Magic.ToLower ' not ok - wanted to avoiding potential bugs if Magic is ever changed.
Public Const Magic2 As String = functionGeneratingLongButStaticString()

大多数情况下的解决方法如下:

''' <summary>Lowercase value of Magic</summary>
Public Shared ReadOnly lcMagic As String = Magic.ToLower

但这并没有提供实际价值的智能感知 而不是&#34;安全&#34;自it is possible to modify ReadOnly fields with reflection

以来

有没有办法宣布&#39; const函数&#39;什么,如果不是,框架如何真正做到这一点?

编辑: 检查生成的IL:

.field public static literal char Cr = char('\r')

这意味着它是编译器的特例。

2 个答案:

答案 0 :(得分:4)

编译器可能会将AscWChrW视为特殊情况。搜索“AscW”的Roslyn源代码会在OptimizeLibraryCall中显示以下内容(为清晰起见,大量代码被剪切):

            ' AscW(char) / AscW(String)
            ' all values can be optimized as a literal, except an empty string that produces a diagnostic
            If IsWellKnownTypeMember(WellKnownMember.Microsoft_VisualBasic_Strings__AscWCharInt32, method) OrElse
                IsWellKnownTypeMember(WellKnownMember.Microsoft_VisualBasic_Strings__AscWStringInt32, method) Then

                '[...]
                Return ConstantValue.Create(AscW(argumentValue))
            End If

            ' ChrW
            ' for -32768 < value or value > 65535 we show a diagnostic
            If IsWellKnownTypeMember(WellKnownMember.Microsoft_VisualBasic_Strings__ChrWInt32Char, method) Then
                '[...]
                Return ConstantValue.Create(ChrW(argumentValue))
            End If

            '[...]

EarlyWellKnownAttributeBinder.CanBeValidAttribute中还有一条注释,它特别提到了可用于属性值的编译时常量类型中的AscWChrW

        ' 11.2 Constant Expressions
        '
        'A constant expression is an expression whose value can be fully evaluated at compile time. 
        ' [...]
        '         The following run-time functions:
        '            Microsoft.VisualBasic.Strings.ChrW
        '            Microsoft.VisualBasic.Strings.Chr, if the constant value is between 0 and 128
        '            Microsoft.VisualBasic.Strings.AscW, if the constant string is not empty
        '            Microsoft.VisualBasic.Strings.Asc, if the constant string is not empty

Mono vbnc编译器似乎有IsConstantMethod helper method来支持这些功能(它专门检查方法是AscWAscChrW ,或Chr),以及test case专门测试const语句是否接受这些功能,这表明它们是特殊情况。

如果你在ildasm中查看已编译的程序集,你会看到:

.field public static literal char Cr = char(0x000D)

你可以看到编译器正在评估函数并发出结果 - 它没有嵌入任何类型的“常量函数”调用,并且参考源中的那些函数没有任何类型的属性修饰将它们标记为一个“不变的功能”。

所以为了回答你的问题,看起来编译器通过将这些字符串函数视为特殊的硬编码情况来做到这一点,并且看起来没有任何方法可以做到这一点,缺少修改编译器代码。

答案 1 :(得分:0)

来自MSDN:

  

您不能在初始化程序中使用变量或函数。 ,您可以使用转化关键字,例如CByte和CShort。如果使用常量String或Char参数调用它,也可以使用AscW,因为可以在编译时对其进行评估

ChrW等是特殊的,因为编译器旨在允许它们:

Private Const vblf As String = ChrW(10)

编译为:

private const char vblf = '\n';

使用.NET功能的大多数其他表单都是非法的:

Private Const vbcr As String = Convert.ToString(New Byte() {13})
Private Const vblf2 As Char = Environment.NewLine

Private Const Z As String = Ziggy.ToLower

即使Ziggy是一个常量,看起来它应该是合法的,但函数结果却不是。非英语系统的返回可能会有所不同,因为当字符串不匹配但应该在运行时出现非常讨厌的问题。