Невозможно привести в строку даже при перегруженном операторе - PullRequest
3 голосов
/ 17 февраля 2012

Используя MVC3 и атрибут проверки StringLength для свойства типа MyType<string>, внутреннее значение которого равно string, я получаю исключение:

Невозможно привести объект типа 'MyType 'для ввода' System.String '.

Итак, я добавил перегрузку оператора, вот мой класс:

public class MyType<T>
{
    public T Value { get; set; }
    //...

    public static implicit operator string(MyType<T> instance)
    {
        //Return the internal value of the instance.
        return Convert.ToString(instance.Value);
    }
}

Так что теоретически это должно разрешить MyTypeБыть приведенным к String.Тем не менее, я все еще получаю ту же ошибку, вот трассировка стека:

[InvalidCastException: Невозможно привести объект типа 'MyType' к типу 'System.String'.]
System.ComponentModel.DataAnnotations.StringLengthAttribute.IsValid (значение объекта) + 64
System.ComponentModel.DataAnnotations.ValidationAttribute.IsValid (значение объекта, ValidationContext validationContext) + 176
Value.lidateAgnodeNoNjectAgnationAgnodeAntAgnateAgnoteNoNateAgnation.NoTalAntAgnationAntementNoTalNateAgnationAntementNoTalAntAgnationAntNameTaltationAntName)... ::. Component. Valid. Valid..... Valid. Val.ValidationContext validationContext) + 41
System.Web.Mvc.d__1.MoveNext () + 267

Метод StringLengthAttribute.IsValid (из среды .NET, а не из моего кода) выполняет следующие действия:

public override bool IsValid(object value)
{
    this.EnsureLegalLengths();
    int num = (value == null) ? 0 : ((string)value).Length;
    return value == null || (num >= this.MinimumLength && num <= this.MaximumLength);
}

Кажется, это должно работать, что мне не хватает?

Ответы [ 3 ]

1 голос
/ 17 февраля 2012

Переменная value объявлена ​​типа object. Сначала вы должны привести к фактическому типу, поскольку базовый объект не является string. Не существует преобразований, определенных из object в другие типы, поэтому выполняемое вами приведение фактически говорит компилятору, что этот объект на самом деле является string, когда это не так. По сути, это правило того же типа, которому необходимо следовать при распаковке типов значений.

Сначала приведя его к вашему типу, компилятор может понять, что существует (неявное) преобразование из вашего типа в желаемый тип string и может сгенерировать соответствующие инструкции.

например,

object obj = new MyObject<string> { Value = "Foobar" };
string x = (string)obj;           // fail: obj is not a string
string y = (MyObject<string>)obj; // obj: obj is cast to MyObject<string> and
                                  //      an implicit cast to string exists
// to be clearer
string z = (string)(MyObject<string>)obj;
0 голосов
/ 17 февраля 2012

Вы используете неявное приведение, и вы должны выполнить явное приведение, потому что среда приведёт это явным образом. Как это:

(string)value

Вы должны добавить:

public static explicit operator string(MyType<T> instance)
{
    //Return the internal value of the instance.
    return Convert.ToString(instance.Value);
}
0 голосов
/ 17 февраля 2012
public override bool IsValid(object value)
{
    this.EnsureLegalLengths();
    int num = (value == null) ? 0 : ((MyType<string>)value).Value.Length;
    return value == null || (num >= this.MinimumLength && num <= this.MaximumLength);
}

Не приводите его к string, но к MyType<string>.

Измененная строка кода для отражения этого:

    int num = (value == null) ? 0 : ((MyType<string>)value).Value.Length;

Правка : не передавайте MyType<string> методу, передайте ему MyType<string>.Value, чтобы приведение было успешным.

...