По параметрам Ref в VB.NET и C#
У меня есть вопросы, связанные с передачей параметров byRef, у меня есть библиотека классов на основе VB.NET, в которой некоторые функции определены с типами аргументов byref. Эти параметры являются объектами родительского класса, и когда я попытался вызвать эту функцию и передать объект дочернего класса в аргументе byref, он работает в VB.NET, но я не могу сделать то же самое в C#
Ниже тестовый код, который я пытаюсь
Public Class Father
Private _Cast As String
Public Property Cast() As String
Get
Return _Cast
End Get
Set(ByVal value As String)
_Cast = value
End Set
End Property
End Class
Public Class Son
Inherits Father
Private _MyName As String
Public Property Myname() As String
Get
Return _MyName
End Get
Set(ByVal value As String)
_MyName = value
End Set
End Property
End Class
Класс реализации в VB
Public Class Parent
Public Function Show(ByRef value As Father) As Boolean
Dim test As String = value.Cast
Return True
End Function
// Здесь я могу вызвать метод Show и передать дочерний объект в аргумент типа ByRef, и это работает
Public Function Show2() As Boolean
Dim s As New Son
Dim result As Boolean = Show(s)
Return True
End Function
End Class
// Но когда я пытаюсь сделать то же самое в C#
Parent p = new Parent();
Son s = new Son();
Father f = new Father();
p.Show(ref s);
Я получаю сообщение об ошибке, что сын не может преобразовать в отца, я уже проверял, что он работает в VB, но как я могу заставить его работать в C#? как у меня есть библиотека классов в формате dll
заранее спасибо
2 ответа
В C# это строго, переменная, передаваемая по ссылке, должна точно соответствовать типу аргумента метода. VB.NET прощает об этом, его компилятор переписывает ваш код и создает переменную требуемого типа. Примерно так, выражаясь в C#:
Son s = new Son();
Father $temp = (Father)s;
p.Show(ref $temp);
s = (Son)$temp;
Что приятно, но не без проблем. Режим сбоя - это когда метод Show() назначает новый объект своему аргументу неправильного типа. Разрешено создавать объект Father, поскольку тип аргумента - Father. Это, однако, приведет к тому, что 4-е утверждение в приведенном выше фрагменте не удастся, не может привести Отца к Сыну. Это не так красиво, исключение будет вызвано неправильным оператором, настоящая проблема находится в методе Show(). Вы можете поразмыслить над этим какое-то время, не в последнюю очередь, потому что приведение фактически не видно в исходном коде VB.NET. Уч. C# заставляет вас написать приведенный выше фрагмент явно, что решает вашу проблему.
На этом этапе вы должны воскликнуть "Но подождите, метод Show() на самом деле не создает новый объект!" Это хорошее понимание, и вы обнаружили истинную проблему в этом коде, метод Show() не должен объявлять аргумент ByRef. Его следует использовать только тогда, когда метод переназначает аргумент, и это изменение необходимо распространить обратно вызывающей стороне. Лучше всего избегать, объект должен быть возвращен методом по возвращаемому значению. Функция в VB.NET вместо Sub.
ByRef
позволяет функции изменять управляемый указатель и указывать на что-то отличное от Son
поэтому C# не позволит вам передать управляемый указатель на Son
непосредственно. Тем не менее, вы можете сделать это:
Son s = new Son();
Father f = s;
p.Show(ref f);
s = (Son)f; //Success if f still points to a Son, InvalidCastException otherwise.
Однако, если ваш метод Show
действительно не изменяет управляемый указатель, то нет причин для его принятия ByRef
: Просто передайте это ByVal
и вы все равно сможете изменить сам объект.