Разница между 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