I want to change some of my entities IDs to strongly typed. And in order to avoid too much code refactoring I used implicit conversions.
Here's what I have so far:
public class FooBarId
{
private readonly Guid _id;
public FooBarId(Guid id)
{
_id = id;
}
public Guid Id
{
get { return _id; }
}
public static implicit operator Guid(FooBarId id)
{
return id.Id;
}
public static implicit operator FooBarId(Guid id)
{
return new FooBarId(id);
}
}
This code works fine and I don't have to change anything else in my code.
But I would like to create much more such classes and in order to avoid repeating myself I created a generic class:
public class CustomId<T>
{
private readonly T _id;
public CustomId(T id)
{
_id = id;
}
public T Id
{
get { return _id; }
}
public static implicit operator T(CustomId<T> id)
{
return id.Id;
}
public static implicit operator CustomId<T>(T id)
{
return new CustomId<T>(id);
}
}
And tried to inherit it in my FooBarId
class:
public class FooBarId : CustomId<Guid>
{
}
And then my code breaks with an exception where FooBarId is used:
Argument type 'System.Guid' is not assignable to parameter type 'FooBarId'
.
When I try to cast it like this foo.bar((FooBarId)new Guid())
- code compiles, but throws an exception later in program execution:
<System.InvalidCastException> (Unable to cast object of type 'CustomId1[System.Guid]' to type 'FooBarId'.)
What am I missing here?
This works for me:
class Program
{
static void Main(string[] args)
{
Guid result1 = (CustomId<Guid>)new CustomId<Guid>(Guid.NewGuid());
Guid result2 = (CustomId<Guid>)new FooBarId();
Guid result3 = (FooBarId)new FooBarId();
Guid result4 = new FooBarId();
CustomId<Guid> cIResult = Guid.NewGuid();
}
}
public class CustomId<T>
{
private readonly T _id;
public CustomId(T id)
{
_id = id;
}
public T Id
{
get { return _id; }
}
public static implicit operator T(CustomId<T> id)
{
return id.Id;
}
public static implicit operator CustomId<T>(T id)
{
return new CustomId<T>(id);
}
}
public class FooBarId : CustomId<Guid>
{
public FooBarId()
: base(Guid.NewGuid())
{
}
}
You cannot do (FooBarId)new Guid()
because a CustomId<Guid>
is not a FooBarId
. You will need to define am implicit operator for each class which converts from Guid
to that class.