Разница между VB.Net и C# "как новый веб-контроль"

Я занимался рефакторингом некоторого кода, и часть его включала в себя перемещение его из VB.Net в C#.

Старый код объявил члена следующим образом:

Protected viewMode As New WebControl

Новый код, в конце концов, я заработал, вот так:

protected WebControl _viewMode = new WebControl(HtmlTextWriterTag.Span);

Я могу предположить, что New Ключевое слово означало: вызвать конструктор! Но как VB.Net вызывал конструктор (без параметров), который я не мог вызвать в C#?

4 ответа

Решение

Причина, по которой это работало в VB, а не в C#, не имела ничего общего со сборками.

Конструктор по умолчанию для WebControl защищен.

VB и C# имеют разные интерпретации того, что означает "защищенный".

В VB вы можете получить доступ к защищенному члену класса из любого метода любого типа, производного от класса.

То есть VB позволяет этот код компилировать:

class Base
    protected m_x as integer
end class

class Derived1
    inherits Base
    public sub Foo(other as Base)
        other.m_x = 2
    end sub
end class

class Derived2
    inherits Base
end class

Поскольку Derived1 является базой, он может получить доступ к защищенным членам "other", которая также является базой.

C# принимает другую точку зрения. Это не позволяет "боковой" доступ, который делает VB. В нем говорится, что доступ к защищенным элементам может быть сделан через "this" или любой объект того же типа, что и класс, который содержит метод.

Поскольку "Foo" здесь определено в "Derived1", C# разрешает "Foo" получать доступ к элементам "Base" только из экземпляра "Derived1". "Другой" может быть чем-то, что не является "Derived1" (это может быть, например, "Derived2"), и поэтому он не разрешает доступ к "m_x".

В этом случае вашего кода VB разрешил "боковой" доступ к конструктору "WebControl".

C#, однако, нет.

Конструктор по умолчанию для WebControl (неявный в строке VB) должен использовать span. Вы можете вызвать этот конструктор в C#, а также VB.NET.

Доступ к унаследованным защищенным конструкторам из производного класса в любом контексте вызовет проблемы инкапсуляции данных.

Исторически, C# с самой первой версии разрешал такой доступ. Но это было исправлено в VS 2005. Производные классы теперь могут вызывать свои базовые защищенные конструкторы только из своего собственного конструктора.

class Base
{
    protected Base()
    {
    }
}

class Derived : Base
{
    public Derived() : base() // Still allowed in VS 2005
    {
    }

    public void Main()
    {
        Base b = new Base(); // Allowed in VS 2003, but error in VS 2005
    }
}

В VB.NET вы можете инициализировать переменные двумя способами. Сначала с оператором присваивания следовало объявление; второй с заявлением "Как новый".

В случае защищенного конструктора, "как новый" всегда работает нормально. Что касается инициализации по присваиванию, это вызовет ошибку компиляции. Но если у вас есть более одного конструктора в базовом классе, инициализация назначения также будет работать!

Class Base
    Protected Sub New()
    End Sub
End Class

Class Derived
    Inherits Base

    Public Sub Main()
        Dim foo As New Base // Allowed
        Dim moo As Base = New Base() // Error if Base has only one constructor
    End Sub
End Class

Вероятно, причина, по которой VB.NET разрешает такой доступ, заключается в совместимости с устаревшим кодом.

Более подробная информация: http://blogs.msdn.com/b/peterhal/archive/2005/06/29/434070.aspx

Webcontrol wc = tab;

Другие вопросы по тегам