从T和字符串隐式转换

时间:2014-10-15 08:49:35

标签: c# .net implicit-conversion

我目前有一个泛型类,它允许使用表达式作为值。

public class Expression<T>
{
    public T Value { get; set; }
    public string ExpressionText { get; set; }

    public static implicit operator Expression<T>(string input)
    {
        if (string.IsNullOrEmpty(input))
            return null;

        if (input.StartsWith("="))
            return new Expression<T> { ExpressionText = input };

        var converter = TypeDescriptor.GetConverter(typeof(T));
        T value = (T)converter.ConvertFromString(input);

        return new Expression<T> { Value = value };
    }

    public static implicit operator Expression<T>(T value)
    {
        if (value == null)
            return null;

        return new Expression<T> { Value = value };
    }

我希望能够使用来自T和来自字符串的隐式转换来设置属性。但是,如果表达式是string类型,则编译器无法决定使用哪种转换。

有一个聪明的方法吗?

谢谢,

肖恩

4 个答案:

答案 0 :(得分:3)

由于better conversion rule

,您无法保留两个隐式运算符并期望使用Expression<string>
  

给定一个隐式转换C1,它从类型S转换为类型   T1,以及从类型S转换为a的隐式转换C2   类型T2,两次转换的更好转换被确定为   如下:

     
      
  • 如果T1和T2属于同一类型,则两种转换都不会更好。
  •   
  • 如果S是T1,则C1是更好的转换。
  •   
  • 如果S是T2,则C2是更好的转换。
  •   
  • 如果存在从T1到T2的隐式转换,并且不存在从T2到T1的隐式转换,则C1是更好的转换。
  •   
  • 如果存在从T2到T1的隐式转换,并且不存在从T1到T2的隐式转换,则C2是更好的转换。
  •   
  • 如果T1是sbyte而T2是byte,ushort,uint或ulong,则C1是更好的转换。
  •   
  • 如果T2是sbyte而T1是byte,ushort,uint或ulong,则C2是更好的转换。
  •   
  • 如果T1很短且T2是ushort,uint或ulong,则C1是更好的转换。
  •   
  • 如果T2很短且T1是ushort,uint或ulong,那么C2就是更好的转换。
  •   
  • 如果T1为int且T2为uint或ulong,则C1为更好的转换。
  •   
  • 如果T2为int且T1为uint或ulong,则C2为更好的转换。
  •   
  • 如果T1很长且T2很大,则C1是更好的转换。
  •   
  • 如果T2很长且T1很大,那么C2就是更好的转换。
  •   
  • 否则,转换都不会更好。
  •   
     

如果这些规则定义的隐式转换C1更好   转换比隐式转换C2,那么情况也是如此   C2的转换率比C1差。

使用Expression<string>显然是第一种情况,编译器不会为您选择并just stop there

  

如果没有一个功能成员比所有功能成员更好   其他函数成员,则函数成员调用   模糊不清,发生编译时错误。

所以你不能仅仅使用转换运算符来处理;或者创建其他方法来显式处理字符串,将字符串转换为运算符外部的T或创建一个包装抽象,它能够传输T,T的字符串表示或ExpressionText值并从中转换。

答案 1 :(得分:1)

定义通用转换和特定类型转换实际上会产生歧义。但是您不需要定义特定的(字符串)转换,因为通用的转换已经涵盖了所有情况。

public class Expression<T>
{
    public T Value { get; set; }
    public string ExpressionText { get; set; }

    public static Expression<T> Convert(string input)
    {
        if (string.IsNullOrEmpty(input))
            return null;

        if (input.StartsWith("="))
            return new Expression<T> { ExpressionText = input };

        var converter = TypeDescriptor.GetConverter(typeof(T));
        T value = (T)converter.ConvertFromString(input);

        return new Expression<T> { Value = value };
    }

    public static implicit operator Expression<T>(T value)
    {
        if (value == null)
            return null;

        var str = value as string;
        if (!string.IsNullOrEmpty(str))
            return Convert(str);
        else
            return new Expression<T> { Value = value };
    }
}

答案 2 :(得分:1)

尝试这个。

namespace ConsoleApplication11
{
    class Program
    {
        static void Main(string[] args)
        {
            Expression<string> str = "1";

        }
    }
    public class Expression<T>
    {
        public T Value { get; set; }
        public string ExpressionText { get; set; }



        public static implicit operator Expression<T>(T value)
        {
            if (value is string) {
                string input = value.ToString();
                if (string.IsNullOrEmpty(input))
                    return null;

                if (input.StartsWith("="))
                    return new Expression<T> { ExpressionText = input };

                var converter = TypeDescriptor.GetConverter(typeof(T));
                T tValu = (T)converter.ConvertFromString(input);

                return new Expression<T> { Value = tValu };
            }
            else if (value == null)
                return null;

            return new Expression<T> { Value = value };
        }
    }
}

答案 3 :(得分:0)

没有什么可以阻止您使用运行时类型检查:

if (input is string) 
    return new Expression<T>(input as string); // delegate to explicit constructor