【问题标题】:implicit conversion from T and string从 T 和字符串的隐式转换
【发布时间】:2014-10-15 08:49:34
【问题描述】:

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

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 和字符串的隐式转换来设置属性。但是,如果表达式是字符串类型,编译器无法决定使用哪种转换。

有没有巧妙的办法解决这个问题?

谢谢,

肖恩

【问题讨论】:

    标签: c# .net implicit-conversion


    【解决方案1】:

    由于better conversion rule,您将无法同时保留隐式运算符并期望使用Expression&lt;string&gt;

    给定一个从类型 S 转换为类型的隐式转换 C1 T1,以及从类型 S 转换为类型的隐式转换 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 是 short 而 T2 是 ushort、uint 或 ulong,则 C1 是更好的转换。
    • 如果 T2 是 short 而 T1 是 ushort、uint 或 ulong,则 C2 是更好的转换。
    • 如果 T1 是 int 而 T2 是 uint 或 ulong,则 C1 是更好的转换。
    • 如果 T2 是 int 而 T1 是 uint 或 ulong,则 C2 是更好的转换。
    • 如果 T1 是 long 而 T2 是 ulong,则 C1 是更好的转换。
    • 如果 T2 是 long 而 T1 是 ulong,则 C2 是更好的转换。
    • 否则,两种转换都不是更好。

    如果隐式转换 C1 被这些规则定义为更好 转换比隐式转换 C2,那么也是这样 C2 的转换比 C1 差。

    使用Expression&lt;string&gt;,您显然属于第一种情况,编译器不会为您选择,而是just stop there

    如果没有一个函数成员比所有成员都好 其他函数成员,则函数成员调用为 模棱两可并且发生编译时错误。

    因此,您将无法仅使用转换运算符;要么创建额外的方法来显式处理字符串,将字符串转换为运算符之外的 T,要么创建一个能够传输 T、T 的字符串表示或 ExpressionText 值并从中转换的包装抽象。

    【讨论】:

    • 感谢您的详细回答。我决定创建一个静态方法来处理字符串的转换并使用 T 的隐式转换,因为这将是两者中最常用的。
    【解决方案2】:

    试试这个。

    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】:

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

      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 };
          }
      }
      

      【讨论】:

      • 如果value 不是string,您的代码只会返回null
      • @DarkWanderer 哦!是的,谢谢你指出这一点,我已经更新了。
      【解决方案4】:

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

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2023-03-24
        • 1970-01-01
        • 1970-01-01
        • 2019-02-15
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-04-19
        相关资源
        最近更新 更多