Как проверить, существует ли явное или явное приведение? - PullRequest
5 голосов
/ 29 ноября 2009

У меня есть универсальный класс, и я хочу обеспечить, чтобы экземпляры параметра типа всегда были "преобразуемыми" / конвертируемыми из String. Можно ли это сделать, например, без использования интерфейса?

Возможная реализация:

public class MyClass<T> where T : IConvertibleFrom<string>, new()
{
    public T DoSomethingWith(string s)
    {
        // ...
    }
}

Идеальная реализация:

public class MyClass<T>
{
    public T DoSomethingWith(string s)
    {
        // CanBeConvertedFrom would return true if explicit or implicit cast exists
        if(!typeof(T).CanBeConvertedFrom(typeof(String))
        {
            throw new Exception();
        }
        // ...
    }
}

Причина, по которой я бы предпочел эту «идеальную» реализацию, главным образом состоит в том, чтобы не заставлять все Ts реализовывать IConvertibleFrom <>.

Ответы [ 3 ]

3 голосов
/ 29 ноября 2009

Учитывая, что вы хотите конвертировать из запечатанного типа String, вы можете игнорировать возможные обнуляемые, бокс, ссылочные и явные преобразования. Только op_Implicit() квалифицируется. Более общий подход обеспечивается классом System.Linq.Expressions.Expression:

using System.Linq.Expressions;
...
    public static T DoSomethingWith(string s)
    {
      var expr = Expression.Constant(s);
      var convert = Expression.Convert(expr, typeof(T));
      return (T)convert.Method.Invoke(null, new object[] { s });
    }

Остерегайтесь стоимости отражения.

0 голосов
/ 29 ноября 2009
if(!typeof(T).IsAssignableFrom(typeof(String))) {
    throw new Exception();
}
0 голосов
/ 29 ноября 2009

Почему ты не можешь сделать что-то подобное?

public class MyClass<T> where T : string
{
    public T DoSomethingWith(string s)
    {
        // ...
    }
}

Таким образом вы можете проверить, можно ли s преобразовать в T в коде DoSomethingWith. Оттуда вы можете выбросить исключение, если не можете, или выполнить приведение, если можете

...