1

I am trying to send a params object[i] to a T function but I cant find the right syntax.

Here is an example to show the context of what I am trying to achieve:

private bool decodeValue<T>(int id,ref T item, string code)
{

    if(!TypeDescriptor.GetConverter (item).CanConvertFrom(typeof(string)))
    {
        errorThrow (id + 2);
        return false;
    }

    try
    {
        item = ((T)TypeDescriptor.GetConverter (item).ConvertFromString (code));
    }
    catch 
    {
        errorThrow (id + 2);
        //item = default(T);
        return false;
    }

    return true;
}

private bool decodeValues(string[] code, int id, params object[] items)
{
    for (int i = 0; i < items.Length; i++) 
    {
        System.Type t = items [i].GetType(); 
        //in this part i cant find the correct syntax
        if(decodeValue<(t)items[i]>(id, ref items[i] as t, code[i+2]))
        {

        }
    }

    return false;
}

At the line decodeValue<(t)items[i]>(id, ref items[i] as t, code[i+2] no matter what syntax I try, the compiler tells me that after > it expects a )

I could inline the function decodeValue into the for loop but I think there is a more elegant way of doing it. Any suggestions?

3
  • also does not work if(decodeValue<typeof(t)>(id, ref items[i], code[i+2])) Commented Oct 5, 2016 at 14:44
  • Why do you need T in the first place? Your code looks like you could just use ref object item Commented Oct 5, 2016 at 14:45
  • because i first made decodeValue and after i said to myself it would be nicer to do it in batch so i added decodeValues and tried to adapt it to decodeValue. decodeValue at first was a good use of template since i was sending every value of a message one by one hard coded. Commented Oct 5, 2016 at 15:03

3 Answers 3

4

In your example, you replace content of items. Why do even need templated function? Just do this:

private bool decodeValue(int id,ref object item, string code)
{

    if(!TypeDescriptor.GetConverter(item).CanConvertFrom(typeof(string)))
    {
        errorThrow (id + 2);
        return false;
    }
    try
    {
        item = TypeDescriptor.GetConverter(item).ConvertFromString(code);
    }
    catch 
    {
        errorThrow (id + 2);
        return false;
    }

    return true;
}

private bool decodeValues(string[] code, int id, params object[] items)
{
    for (int i = 0; i < items.Length; i++) 
    {
        //in this part i cant find the correct syntax
        if(decodeValue(id, ref items[i], code[i+2]))
        {

        }
    }

    return false;
}

If you ever need type of item in your code, just call .GetType() where it actualy needed. That is not only good way to do things, but in some cases performance effective (compiler can greatly optimise some calls of this function).

Sign up to request clarification or add additional context in comments.

1 Comment

thanks this is what happen when you add stuff on something without thinking of changing the base design. Instead of adapting decodeList for decodeValue i should have done the reverse.
2

generics (<T>) and reflection (.GetType()) are not good friends. There is no convenient way to express that. You can, however, abuse dynamic to do it, but you can't easily use ref in that case. Further, you can't ref between an object and a T. So basically, there's a lot of hurdles. Frankly, I think you should assess whether decodeValue<T> really needs to be generic. In this scenario - especially when using TypeDescriptor - I very much doubt that it needs to be. I suspect your best bet would be to have:

private bool DecodeValue(int id, ref object item, Type type, string code)

4 Comments

the function decode in batch a server communication in a form of string
@CedricRaymond I'm not sure what that would change, if anything... that doesn't make generics a good or bad fit...
each function have a different set of parameter that has to be decoded and checked for error the type can be int, byte, long, string, bool, DateTime
@CedricRaymond again... that doesn't change anything. Without seeing where you are using T in decodeValue<T>, I strongly suspect that it isn't needed. In particular, you're using TypeConverter, and TypeConverter works with Type, not <T>
0

The generics' syntax if for compile time while GetType() is for runtime. You cannot mix them of use them together.

A generic class is resolved while you source is converted to binary. The type or interface provided in a generic type is used in that area.

On the contrary GetType returns a type during execution. That type cannot be inserted in a generic definition because compilation has already be done at that time.

2 Comments

Actually this isn't quite true; IL is much more flexible than you might think, and everything you mention can be done with types not known until runtime. It just isn't convenient. For example, you can use MethodInfo.MakeGenericMethod - or much more conveniently, there are ways to use dynamic to get the runtime to make the switch. But it is inelegant, and usually means you shouldn't be doing that in the first place. The key point is that with C# (in contrast to Java or C++), the generic type information is retained during compilation; it is not erased by the compiler
because of the webgl target i cant use reflection This is really annoying, otherwise i would never had this problem

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.