views:

328

answers:

5

I have a generic method that copies values between value types. The following approaches give a design time error, even with the struct constraint. Any idea how I can copy or cast between the values?

    private Ttgt MyMethod<Tsrc,Ttgt>(Tsrc SourceObject) 
        where Tsrc:struct
        where Ttgt:struct
    {
        //Error:cannot implictly convert type 'Tsrc' to 'Ttgt'
        Ttgt returnObject = SourceObject; 

        //Error:Cannot convert type 'Tsrc' to 'Ttgt'
        Ttgt returnObject = (Ttgt)SourceObject; 

        return returnObject;
    }
+1  A: 

//Error:Cannot convert type 'Tsrc' to 'Ttgt'

You cannot convert between arbitrary types, unless there is an accessible conversion operator.

Richard
+1  A: 

The two are defined as different types. Even though they are both structs, they are not the same types.

Define both souce and target as the same type:

private T MyMethod<T>(T source, T target)
{
Andrew Robinson
+3  A: 

Given that there is a registered type converter for the types that you're trying to convert between a little reflection magic could do the trick:

private Ttgt MyMethod<Tsrc,Ttgt>(Tsrc sourceObject) 
    where Tsrc:struct where  Ttgt:struct    
{    
    Type targetType = typeof(Ttgt);
    TypeConverter tc = TypeDescriptor.GetConverter(targetType);
    Ttgt returnObject = (Ttgt)tc.ConvertTo(sourceObject, targetType);
    return returnObject;    
}

But out of the box it would be of very limited use since there is no converter between bool and int for example. What problem are you trying to solve?

I also discovered another question with some crazy conversion code in it.

Edit: Your comment makes it clear that you are trying to perform object to object mapping between domain objects and some kind of view/contract model. Have you looked at AutoMapper?

PHeiberg
I am writing a recursive object-to-object mapper. to seperate the contract classes from the underlying business logic classes in a WCF implementation. The implementation classes are near identical to the contract but I don't want to introduce a dependency between the two.
Jon Simpson
This should say: Type targetType = typeof(Ttgt);
mike nelson
Thanks. Updated variable names to be correct.
PHeiberg
A: 

This is "By Design." You are attempting to cast between two unrelated value types. This will never succeed and therefore it is flagged as an error.

This will be true of all value typse because they are implicitly sealed. In order for a cast between TSrc -> Ttgt to succeed, there must be a class hierarchy relationship between the two types. This cannot be because all value types are sealed hence there is no way one can derive from the other.

The only way this could succeed is if one had a custom conversion operator between the types. This may be the case. However when dealing with generic types, custom conversion operators will not be processed.

JaredPar
A: 

The Convert class exists for this exact purpose.

private Ttgt MyMethod<Tsrc, Ttgt>(Tsrc SourceObject)
    where Tsrc : struct
    where Ttgt : struct
{
    return (Ttgt) Convert.ChangeType(SourceObject, typeof(Ttgt));
}

Also note that you could do this:

    return (Ttgt) (object) SourceObject;
kek444