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//只有名称是“可见的”


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...

// 共享成员的行为就像一个公共类我可以重复它到无限..

这是 Microsoft 的疏忽还是 VB.NET 的“功能”?

4

3 回答 3

20

这不是疏忽,但您的 VB 代码触发警告,这显然意味着:不要使用这种表示法。

在 VB 中,静态成员可以通过实例访问,因为严格来说,VB没有static: VB 有关键字Shared,这意味着成员在所有实例之间共享static,而不是成员不属于任何实例.

现在,这是这些关键字之间的语义区别。碰巧这两种不同的语义往往具有完全相同的效果。

当然,static今天的 C# 与SharedVB.NET 相同,但它们的遗产不同,而 VBShared只是具有不同的历史,因此在历史上具有不同的含义。有了这个Shared含义,通过实例访问成员是绝对有意义的。

Option Strict Off与(loose typing)一起使用时也有意义:在这里,您有时不知道变量的类型,但您仍然可能想要访问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
于 2009-12-30T13:47:48.630 回答
11

这是一个特点;这不是错误。VB 正在按设计工作。不同的语言对是否可以将静态方法视为实例的方法做出不同的选择。VB允许它。C++ 允许它。C# 没有。

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

在 VB 设计团队中,他们重视代码在您第一次键入时的工作方式;如果有些东西看起来有点狡猾,也许会发出警告,但允许它继续前进。

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

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

于 2009-12-30T15:22:13.203 回答
0

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

于 2009-12-30T13:49:22.093 回答