I found this bug when assigning large database ID keys from Ruby to a .NET data set. RubyCLR will convert a Bignum value
to a System.Double when passsing to a method that takes an Object parameter (such as DataRow's set_Item method). The
code below gives a unit test which demonstrates the problem. Note this was developed with "Drop 4" of RubyCLR,
I don't know if it works with later versions:
# == Begin Here
# Contributed by Justin Bailey (jgbailey @nospam@ gmail.com)
#
require 'rubygems'
require 'rubyclr'
require 'test/unit'
class Int64MarshalTest < Test::Unit::TestCase
# Create two methods, one that takes an Int64 argument,
# the other that takes a Object argument
inline do |csharp|
csharp.compile <<-CS
public class Class1
{
public static System.Int64 returnArgObject(object arg)
{
// Argument here is actually a double (from RubyCLR)
return System.Convert.ToInt64(arg);
}
public static System.Int64 returnArgInt64(System.Int64 arg)
{
return arg;
}
}
CS
end
def test_precision_loss
# RubyCLR converts the value below
# into a double when passing it to returnArgObject
#
# This causes a loss of precision when the value comes back.
# This is bad when that value is a database ID and
# it is being assigned to a .NET data set from Ruby ...
int64 = 616013000000000008
# This works because RubyCLR correctly marshals to a In64
result = Class1.returnArgInt64(int64)
assert int64 == result, "int64 did not come back from returnArgInt64 with the same value. Instead, came back
as: #{result}"
# This fails because int64 is passed as a Double type
# to returnArgObject.
result = Class1.returnArgObject(int64)
assert int64 == result, "int64 did not come back from returnArgObject with the same value. Instead, came back
as: #{result}"
end
end
|