Как я могу привести объект к строке, если объект не является строкой? - PullRequest
2 голосов
/ 21 марта 2010

-Edit- Альтернативный вопрос / пример Как я могу привести A к объекту класса A, когда B может набрать A?


У меня есть класс A, B, CВсе они могут неявно преобразовывать в строку

public static implicit operator A(string sz_) {  ... return sz; }

У меня есть код, который делает это

object AClassWhichImplicitlyConvertsToString

{
    ...
    ((IKnownType)(String)AClassWhichImplicitlyConvertsToString).KnownFunc()
}

Проблема в том, что AClassWhichImplicitlyConvertsToString не является строкой, даже если она может быть приведена в одну неявно,У меня плохое исключение.Как мне сказать, что все в порядке, если в классе есть оператор для преобразования в строку?

1 Ответ

8 голосов
/ 21 марта 2010

Существует почти наверняка лучший способ сделать то, что вы пытаетесь сделать. Если вы предоставите больше контекста, вы получите более полезные ответы.

Если вместо (или также) сделать ваши классы неявно скрытыми для строковых, вы также даете им переопределение ToString, тогда вы можете сказать:

((KnownType)AClassBlah.ToString()).KnownFunc()

Однако вы получите исключение при попытке привести строку в KnownType. Поэтому я должен спросить: почему вы пытаетесь пройти через string в этой ситуации? Кастинги, как правило, отвратительная вещь, которая заставляет вас думать: «Может быть, мой дизайн нуждается в рефакторинге однажды». Это не то, что вы создаете в своей библиотеке классов в качестве рекомендуемого шаблона использования. Это низкоуровневое средство с предсказуемым поведением, поэтому нет способа (и нет веских причин предоставить способ) переопределить то, что делает явное приведение.

Update

Судя по вашему комментарию, вы смешиваете полиморфизм времени выполнения и статическое преобразование (время компиляции). Они не слишком хорошо смешиваются. Вы ранее пользовались языками с динамической типизацией? Похоже, что вы могли бы быть. Если у вас есть метод:

void FiddleWithObject(object obj)
{
    // whatever
}

Тогда автор этого метода не знает во время компиляции, какие операции доступны в obj. Поэтому они могут сказать:

void FiddleWithObject(object obj)
{
    if (obj is IFiddly)
    {
        // Cool
        obj.Fiddle();
    }
    else
        throw new Exception("Wrong type of object");
}

Это затем взрывается во время компиляции для классов, которые не IFiddly. Но в статически типизированном языке вы можете сказать:

void FiddleWithObject(IFiddly obj)
{
    obj.Fiddle(); 
}

Это взорвется во время компиляции, если будет передан неправильный тип объекта, и вам не нужно ничего проверять во время выполнения. Меньше кода, ошибки найдены раньше ... насколько это аккуратно?

Функция неявного преобразования является частью перегрузки набора функций оператора. Все они очень привязаны к статическим типам. Они разрешаются во время компиляции на основе известного типа объекта. Так что, если вы не знаете фактический класс объекта, нет (встроенного) способа вызывать операторы на нем. Это просто не смешивается с динамической типизацией.

Если можно получить строку (например, «имя») из объекта IFiddly, то вы можете сделать это свойством этого интерфейса:

public interface IFiddly
{
    void Fiddle();
    string Name { get; }
}

Или (как я уже отмечал ранее) вы можете просто переопределить ToString для любого объекта, так как это метод virtual в классе object, от которого в конечном итоге наследуются все классы. Итак, сказав:

var str = someObject.ToString();

Вы будете вызывать реализацию ToString, определенную в любом классе, someObject является экземпляром.

В итоге:

  • виртуальные и абстрактные методы и поддерживаемые интерфейсы: они предназначены для динамической типизации, времени выполнения и полиморфизма.
  • оператор и неявная перегрузка преобразования (и обобщенные значения): они предназначены для статической типизации во время компиляции.
  • броски отвратительны.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...