我目前有一个泛型类,它允许使用表达式作为值。
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类型,则编译器无法决定使用哪种转换。
有一个聪明的方法吗?
谢谢,
肖恩
答案 0 :(得分:3)
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