Teejay
Teejay

Reputation: 7471

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

Upvotes: 5

Views: 369

Answers (2)

ZoolWay
ZoolWay

Reputation: 5505

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.

Upvotes: 3

Patrick Hofman
Patrick Hofman

Reputation: 156948

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.

Upvotes: 2

Related Questions