2011-07-30 41 views
9

Tại sao mã sau đây ném một ngoại lệ vào thời gian chạy, trong khi thực hiện nó theo cách truyền thống biên dịch mà không có vấn đề?Toán tử nhị phân Nhân không được định nghĩa cho các kiểu 'System.Int32' và 'System.Double'.

var left = Expression.Constant(25d); 
var right = Expression.Constant(20); 

// Throws an InvalidOperationException! 
var multiplyExpression = Expression.Multiply(left, right); 

var multiply = 25d * 20; 
Debug.WriteLine(multiply.ToString()); // Works normally! 

Tôi sẽ không sử dụng Expression.Convert vì tôi không thể xác định chính xác biểu thức nào cần được chuyển đổi.

+4

Bởi vì theo cách truyền thống, trình biên dịch chèn (tương đương đạo đức) một 'Expression.Convert' - sử dụng các quy tắc ưu tiên kiểu để xác định phía nào cần chuyển đổi. –

+0

Trình biên dịch C# nào đã chuyển đổi trong trường hợp này? –

+1

Chỉ cần kiểm tra loại "nhân", điều đó sẽ cho bạn biết nhu cầu phụ nào được chuyển đổi. – MerickOWA

Trả lời

7

Vâng, tôi đã tìm ra cách giải quyết vấn đề bằng cách sử dụng kiểu liệt kê TypeCode để xác định nút nào có độ chính xác loại cao hơn, sau đó chuyển đổi loại nút sau thành kiểu cũ, và ngược lại:

private static void Visit(ref Expression left, ref Expression right) 
    { 
    var leftTypeCode = Type.GetTypeCode(left.Type); 
    var rightTypeCode = Type.GetTypeCode(right.Type); 

    if (leftTypeCode == rightTypeCode) 
     return; 

    if (leftTypeCode > rightTypeCode) 
     right = Expression.Convert(right, left.Type); 
    else 
     left = Expression.Convert(left, right.Type); 
    } 
+0

Oh dam ... TypeCode không khả dụng trên Windows Store. rất gần ...; ( –

0

Thông báo lỗi trong tiêu đề của bạn cho bạn biết tại sao có ngoại lệ.

Không có phương pháp Expression.Multiply được xác định có số System.Int32System.Double làm đối số.

* sẽ hoạt động vì mức độ thấp hơn và giá trị của bạn sẽ được nhập tự động.

0
var left = Expression.Constant(25d); 
var right = Expression.Constant((double)20); 

var multiplyExpression = Expression.Multiply(left, right); // works 
+0

Điều này không thể được thực hiện trực tiếp, tôi nên gọi Expression.Convert bằng cách nào đó. –

7
var left = Expression.Constant(25d); 
var right = Expression.Constant(20); 
var multiplyExpression = Expression.Multiply(
    left, 
    Expression.Convert(right, left.Type)); 

Hoặc, nếu bạn không biết rằng ở phía bên trái có độ chính xác cao hơn, và bạn muốn luôn luôn kết thúc với một kết quả double, bạn có thể nói cái gì đó như:

Expression left = Expression.Constant(2); 
Expression right = Expression.Constant(25.1); 
left = Expression.Convert(left, typeof(double)); 
right = Expression.Convert(right, typeof(double)); 
var multiplyExpression = Expression.Multiply(left, right); 
+0

Vâng, điều này có vẻ tốt, nhưng làm thế nào điều này có thể được thực hiện nếu các toán hạng là loại float, thập phân? –

+1

@Islam Ibrahim: Có một số khả năng và tốt nhất là nên sử dụng chiến lược đơn giản nhất sẽ hoạt động cho mục đích của bạn. Có lẽ nếu bạn chia sẻ thêm thông tin về các yêu cầu của bạn và những gì được sử dụng cho, chúng tôi có thể giúp bạn tìm ra giải pháp phù hợp. Ví dụ: bạn có biết loại bạn muốn kết thúc trước hay không, hoặc điều đó có thay đổi tùy theo đầu vào không? – StriplingWarrior

Các vấn đề liên quan