Присвоить строку, содержащуюся в переменной объекта, строковому свойству динамического элемента (C #) - PullRequest
4 голосов
/ 02 июля 2010

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

public class TypeWithString
{
    public string MyString { get; set; }
}

string s = "We Want Moshiach Now";
TypeWithString tws = new TypeWithString();
object o = s;
dynamic d = tws;
d.MyString = o;

Этот код неожиданно генерирует ошибку RuntimeBinderException: Cannot implicitly convert type 'object' to 'string'. Даже если MyString относится к типу string и что в o содержится string.

это ошибка или недостаток в DLR?

Есть ли способ обойти это?

Если я не знаю тип заранее. Но я знаю, что это соответствует типу утки. я знаю, что он реализует неписаный интерфейс. Можно ли в любом случае назначить одну переменную другой, когда они действительно имеют правильный тип?

Большое спасибо

Ответы [ 2 ]

4 голосов
/ 02 июля 2010

Нет, это ожидается. Компилятор знает, что тип o равен object, поэтому он записывает динамическое действие «попытаться найти свойство с именем MyString, а затем попытаться присвоить ему значение типа object» - это может сделать что если бы было неявное преобразование object в string, но это не так. Обратите внимание, что единственная часть вашего оператора, которая является динамической, это target этого ... так что это единственный бит, который обрабатывается динамически. Во время выполнения «компилятор времени выполнения» фактически скажет: «Каков фактический тип значения d? Ах, это TypeWithString ... что бы произошло, если бы мы имели:

TypeWithString tmpD = (TypeWithString) d;
tmpD.MyObject = o;

... и что произойдет, будет ошибка во время компиляции.

Если вы хотите, чтобы оно также действовало динамически в значении, просто используйте dynamic вместо object для присваиваемого вами значения:

string s = "We Want Moshiach Now";
TypeWithString tws = new TypeWithString();
dynamic o = s;
dynamic d = tws;
d.MyString = o;

На этот раз «компилятор времени выполнения» запросит у себя фактический тип значений d и o и представит код, подобный следующему:

TypeWithString tmpD = (TypeWithString) d;
string tmpO = (string) o; // Actual type is string at execution time
tmpD.MyObject = tmpO;
1 голос
/ 02 июля 2010

Вы всегда можете попробовать d.MyString = o as string;, который приведёт (без броска) o к строке или к нулю, если приведение не существует.

...