Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Runtime implicit cast from object

We created Id32 and Id64 struct to wrap integers and long values coming from DB, so they can be explicitly processed as IDs by a Json converter (with dedicated custom converters).

The problem is that we read this data from a Dictionary<string, object> that actually is a DataRow-like object where the string part is the name of the column and the object part is the value.

So before we had this code to read the value:

int myVal = (int)row["COLUMN"]

We want this code to continue working also after these changes.

But since row["COLUMN"] is an object (@ compile-time) the implicit cast fails, even though it is actually an Id32 (@ run-time).

The following obviously works:

int myVal = (Id32)row["COLUMN"]

But is there some to way to fix this without modifying the code that reads the value?

This is the struct code:

public struct Id32
{
    public readonly int Value;

    public Id32(int id) { this.Value = id; }

    public static implicit operator int(Id32 id) { return id.Value; }

    public static implicit operator Id32(int id) { return new Id32(id); }
}
like image 726
Teejay Avatar asked Jul 07 '15 11:07

Teejay


2 Answers

I think this is not possible with the constraint not to modify your retrieving code int myVal = (int)row["COLUMN"].

You would need to add an implicit cast to object (to int) which cannot be done. There are many ways to make your own cast simple but everyone I can think of or you will find like here requires to change that line.

Even if you not change it I guess you will have to recompile it - so if you recompile it, why not change it? There are some refactoring tools which should make even thousands of that lines quite easy.

like image 61
ZoolWay Avatar answered Oct 26 '22 23:10

ZoolWay


In my opinion not a very decent solution, but it works (hope there are better solutions): if you use dynamic the underlying type is determined on run-time, so the type check with the implicit cast will work.

The code I have used:

dynamic o = new Id32(1);
// dynamic o = row["COLUMN"]; in your case

int myVal = (int)o;

If you change dynamic to object you will have your current situation, which fails.

like image 30
Patrick Hofman Avatar answered Oct 26 '22 23:10

Patrick Hofman