2

I have something like this

V Func<V>()
{
  // do stuff
  V res = default(V);
 // more stuff
  return res;
}

The problem is that I want res to be either 0 or a new instance of V

I tried creating 2 methods

Func<V> where T: new()
Func<V> where T: struct

but surprisingly this is not allowed

My workaround is to have 2 functions

FuncNew<V> where T: new()
...
res = new V();
....

and

FuncDefault<V> where T: struct
...
res = default(V)
...

EDIT: Summarize answers

new(T) will new up a ref or value type; I did not realize that

pm100
  • 48,078
  • 23
  • 82
  • 145
  • 1
    What is to determine whether the return value is a new instance of `V` or 0? – Oded May 18 '11 at 20:28
  • You haven't even written a proper method declaration, and the constraint of `where T : new` is invalid. Even if it *were* valid, you can't overload methods by type constraints. – Jon Skeet May 18 '11 at 20:28
  • 4
    On your attempted solution, [constraints are not part of the signature](http://blogs.msdn.com/b/ericlippert/archive/2009/12/10/constraints-are-not-part-of-the-signature.aspx). – Anthony Pegram May 18 '11 at 20:28
  • @Jon Skeet, is it possible to do what I want – pm100 May 18 '11 at 20:47
  • @Oded - if V is value type then 0, if V is ref type then new – pm100 May 18 '11 at 21:22
  • @pm100: thecoop has already shown you that it's possible to do what you want. – Jon Skeet May 18 '11 at 21:59

2 Answers2

6

You can use the new() constraint:

private V Func<V>() where V : new()
{
  // do stuff
  V res = new V();
 // more stuff
  return res;
}

Value types will be initialized to all-zeros, and any reference types will be initialized using their no-args default constructor.

If the reference type doesn't have a no-args constructor it can't be used with this method, and you'll have to use other ways (there are plenty of solutions to this problem elsewhere on SO, eg Passing arguments to C# generic new() of templated type)

Community
  • 1
  • 1
thecoop
  • 45,220
  • 19
  • 132
  • 189
0

So you want the result object to be integer zero, or a new instance of your generic type? That's not possible because the generic type parameter would only be valid for the integer type unless you specify object as the return type.

public object Func<T>()
     where T: new()
{
    if(something)
       return 0;

    return new T();
}

If you're trying to make a default initializer, you just need to new up the type. This should work for both integer and reference types.

public T Func<T>()
{
    return Activator.CreateInstance<T>();
}
Tejs
  • 40,736
  • 10
  • 68
  • 86
  • Generally, it's better to use `new T()` rather than `Activator.CreateInstance` directly, as the C# compiler inserts some optimizations to make it very fast for value types. – thecoop May 18 '11 at 20:37
  • Indeed. After looking at your implementation, `new()` is more concise. – Tejs May 18 '11 at 20:38
  • the 'something' I would need to test is whether V is ref or value type – pm100 May 18 '11 at 20:49
  • `if(typeof(T).IsSubclassOf(typeof(ValueType)))` should do the trick. – Tejs May 19 '11 at 13:21