在VB.NET和C#中,static/Shared关键字表示可见性。

9

我在VB.NET和C#(.NET2)中遇到了一个关于静态/共享成员可见性的情况。在VB.NET中,这种情况对我来说有点奇怪:

    public class A 
    {
        private static A instance;
        public static A Instance 
        {
            get { return instance; }
        }

        public string Name { get { } }
    }

使用方法

A.Instance.Name // 仅限 Name 是“可见的”

VB.NET:

Public Class A
  Private Shared _instance As A

  Public Shared ReadOnly Property Instance() As A
    Get
      Return _instance
    End Get
  End Property


  Public ReadOnly Property Name() As String
    Get
      Return ""
    End Get
  End Property

End Class

用法:

A.Instance.Instance.Instance.Instance...

// 共享成员的行为与类公共成员的行为相同,可以无限重复使用..

这是微软的疏忽还是 VB.NET 的“特性”?


3
如果这是真的,我就会把它加到我的“为什么选择C#而不是VB”的清单上;-) - Adam Ralph
5
@AdamRalph:这将是过早和没有经过深思熟虑的。 - Konrad Rudolph
3个回答

20
这并非疏忽,而是你的VB代码会触发警告,这意味着:不要使用此记法。
在VB中,静态成员可以通过实例访问,因为严格来说,VB没有static关键字:VB有关键字Shared,意味着成员在所有实例之间共享,而不是static,其中成员不属于任何实例。
现在,这是这些关键字之间的语义区别。恰好这两个不同的语义往往具有完全相同的效果。
当然,C#中的static今天与VB.NET中的Shared相同,但它们的遗留问题是不同的,VB的Shared仅具有不同的历史和因此具有不同的含义。基于这个含义,通过实例访问Shared成员绝对是有意义的。
当与Option Strict Off(松散类型)一起使用时,这也是有意义的:在这里,有时您不知道变量的类型,但仍可能想要访问Shared成员。现在,您别无选择,只能使用实例来访问它:
Option Strict Off
' … '
Dim o As Object = New A()
' Somewhere else, we want to access a static member of A but we don’t know A: '
Dim instance = o.Instance

C#似乎比VB.NET更准确和清晰,应该考虑到它与VB系列的“历史”兼容性。无论如何,C#不允许在类名和类实例通过可见性中重复静态成员。此外,它还防止了“无限化”字段调用,例如Instance.StaticMember.StaticMember...这可能会使类实例的用户感到尴尬。 - serhio

11

这是一个功能,而不是错误。VB按设计运行。不同的语言在静态方法是否可以被视为实例方法方面做出不同的选择。VB允许它。C++允许它。而C#则不允许。

请记住,不同语言的设计标准不同,因此所做的决策也不同。在C#设计团队中,我们高度重视语言定义,以使看起来可疑的非法模式成为不可能;既然将实例作为接收器传递给静态方法没有意义(除非计算接收器表达式会导致副作用),为什么要允许用户键入无意义的代码呢?

在VB设计团队中,他们重视代码在第一次输入时就能以预期工作的方式工作; 如果某些代码看起来有些可疑,也许可以发出警告,但允许其并继续前进。

如果你对C#静态调用设计中的一些更微妙的问题感兴趣,这里是一个有趣的问题:

http://blogs.msdn.com/ericlippert/archive/2009/07/06/color-color.aspx


实际上,由于我认为我的实例比共享更加“静态”,所以我没有预料到在单例“实例”中会有一个以上的“实例”,因此... - serhio

0

C#编译器不允许您在对象的实例上引用静态属性,只能在类型本身上引用。这是C#而不是.NET CLR的限制。VB.NET可以允许此操作,但会发出警告。


这是一个C#限制,而不是.NET CLR的限制。在我看来,这个限制是很好的,因为它不会通过类名和类实例重复静态成员的可见性。此外,这可以防止“无限化”字段调用,例如Instance.StaticMember.StaticMember.StaticMember.StaticMember.StaticMember... - serhio

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接