Терминология "динамически типизированная", к сожалению, вводит в заблуждение. Все языки статически типизированы, а типы - это свойства выражений (а не значений, как думают некоторые). Однако некоторые языки имеют только один тип. Они называются унифицированными языками. Одним из примеров такого языка является нетипизированное лямбда-исчисление.
В нетипизированном лямбда-исчислении все члены являются лямбда-членами, и единственная операция, которая может быть выполнена на члене, применяется к другому члену. Следовательно, все операции всегда приводят либо к бесконечной рекурсии, либо к лямбда-термину, но никогда не сигнализируют об ошибке.
Однако если бы мы увеличили нетипизированное лямбда-исчисление с примитивными числами и арифметическими операциями, тогда мы могли бы выполнять бессмысленные операции , добавляя вместе два лямбда-члена: (λx.x) + (λy.y)
. Можно утверждать, что единственная нормальная задача - сигнализировать об ошибке, когда это происходит, но чтобы это сделать, каждое значение должно быть помечено индикатором, указывающим, является ли этот термин лямбда-термином или числом. Затем оператор добавления проверяет, действительно ли оба аргумента помечены как числа, а если они нет, сообщите об ошибке. Обратите внимание, что эти теги являются типами not , потому что типы являются свойствами программ, а не значениями, создаваемыми этими программами.
Uni-typed language, который делает это, называется динамически типизированным.
Все языки, такие как JavaScript, Python и Ruby, являются унифицированными. Опять же, оператор typeof
в JavaScript и функция type
в Python имеют вводящие в заблуждение имена; они возвращают теги, связанные с операндами, а не их типы. Аналогично, dynamic_cast
в C ++ и instanceof
в Java do not делают проверки типа.
Извинения за короткий ответ, но не, спецификация языка C# запрещает его.
Видят этот ответ к другому вопросу видеть то, что происходит, когда Вы пробуете. Это также говорит, почему Вы не должны делать свойство просто быть общедоступным полем для обхождения ограничения.
Hope это помогает
РЕДАКТИРОВАНИЕ: Вы спрашиваете Почему?
Вы передаете переменную out
или ref
параметр, Вы на самом деле передаете адрес (или местоположение в памяти) переменной. В функции компилятор знает, где переменная действительно, и получает и пишет значения в тот адрес.
свойство А похоже на значение, торцы, это - на самом деле пара функций, каждого с различной подписью. Таким образом для передачи свойства необходимо было бы на самом деле передать два указателя функции, один для получения, и один для набора.
Thats совершенно другая вещь передать функции, чем адрес переменной
т.е. один переменный v's адреса два указателя функции.
Обновление
, Почему не делает C# просто, заботится об этом для нас?
я не Eric Lippert , но я буду делать попытку того, почему
, Что должно подпись функции, которую Вы вызываете быть?
Позволяет, говорят, что Вы хотите звонить void MyFn(ref int i)
, который должен остаться тем путем, или он должен измениться, чтобы сказать, что мы также позволяем свойства? Если это изменяется на некоторый синтаксис как void MyFn(prop_ref int i)
затем, это довольно бесполезно, Вы не можете передать свойства библиотечным функциям или стороннему коду, который не был написан со специальным prop_ref модификатором. Так или иначе я думаю, что Вы предлагаете, чтобы это не должно было отличаться.
Теперь позволяет, говорят MyFn
передачи i
к функции COM или вызову WinAPI, передавая адрес i
(т.е. за пределами .NET, касательно). Если это - свойство, как Вы получаете адрес i
? Не может быть никакого фактического интервала под свойством для получения адреса. Вы делаете то, что делает VB.Net?
Vb. Сетевой компилятор определяет, когда свойство передается как аргумент ByRef методу. В той точке это объявляет переменную, копирует свойство в переменную, передает переменную byref и затем после того, как метод называют, копирует переменную назад в свойство. т.е.
MyFunc(myObject.IntProperty)
становится
Dim temp_i As Integer = myObject.IntProperty
MyFunc(temp_i)
myObject.IntProperty = temp_i
, Любых побочных эффектов свойства не происходит до MyFunc
возвраты, которые могут вызвать все виды проблем и привести к [1 116] очень тонкие ошибки.
По моему скромному мнению Vb. Сетевое решение этой проблемы также повреждается, таким образом, я не собираюсь признавать что как ответ.
, Как Вы думаете, компилятор C# должен обработать это?
Другие объяснили, что Вы не можете сделать этого в C#. В VB.NET Вы можете делать это, даже с опцией, strict/explicit на:
Option Strict On
Option Explicit On
Imports System.Text
Module Test
Sub Main()
Dim sb as new StringBuilder
Foo (sb.Length)
End Sub
Sub Foo(ByRef x as Integer)
End Sub
End Module
вышеупомянутый код эквивалентен этому коду C#:
using System.Text;
class Test
{
static void Main()
{
StringBuilder sb = new StringBuilder();
int tmp = sb.Length;
Foo(ref tmp);
sb.Length = tmp;
}
static void Foo(ref int x)
{
}
}
Лично я рад, что C# не имеет этого - он пачкает воды довольно много, особенно с точки зрения значения свойства, если параметр устанавливается в рамках метода, но затем исключение выдается.
РЕДАКТИРОВАНИЕ: Согласно просьбе мое обоснование относительно того, почему я верю передающим свойствам в, пачкает воды. Если Вы передаете нормальную переменную ссылкой, то та переменная оценена каждый раз, когда на нее ссылаются в рамках метода. Если значение изменяется по некоторым причинам (например, как побочный эффект некоторой другой работы в методе) затем, что изменение будет сразу видимо в методе. Это не имеет место, если Вы передаете свойство ссылкой в VB.NET: метод считывания свойства вызывается однажды, и затем метод set свойства вызывается однажды. Это не похоже, Вы являетесь передающими в, "вот , свойство - получает и установило от этого каждый раз, когда Вы используете параметр".
Вот полный пример, где передача поля и передача совершенно тривиального свойства в.NET имеют совсем другие результаты:
Option Strict On
Option Explicit On
Imports System.Text
Class Test
Dim counter as Integer
Property CounterProperty As Integer
Get
Return counter
End Get
Set (ByVal value as Integer)
counter = value
End Set
End Property
Sub Increment
counter += 1
End Sub
Shared Sub Main()
Dim t as new Test()
Console.WriteLine("Counter = {0}", t.counter)
t.Foo(t.counter)
Console.WriteLine("Counter = {0}", t.counter)
t.CounterProperty = 0
Console.WriteLine("CounterProperty = {0}", t.CounterProperty)
t.Foo(t.CounterProperty)
Console.WriteLine("CounterProperty = {0}", t.CounterProperty)
End Sub
Sub Foo(ByRef x as Integer)
x = 5
Increment
Increment
Increment
x += 1
End Sub
End Class
Вместо этого необходимо сделать что-то вроде этого
WhatEverTheType name;
Test(out name);
// Choose one of the following construction
Person p = new Person();
p.Name = name;
Person p = new Person(name);
Person p = new Person(Name => name);