2

I was reading this question where one answered suggests this method:

public static void Method<T>(Func<int,T> del) {
  var t = del(42);
}

Which should be used like so: Method<SomeType>(x => new SomeType(x));
The Method body is not important to this question. If the delegate/lambda is not in that "style", the method will not work as expected. For example, if it is called like Method(x => new Foo()); it will not "work" because the purpose of the workaround will be lost.
The purpose is ensuring that T has a constructor taking 1 parameter of type int. I wish I could do T(int) So is there anyway to ensure that the delegate should always be be x => new SomeType(x)? Or is there any alternative? I have looked up a lot of places and can't come up with anything.

Community
  • 1
  • 1
wingerse
  • 3,670
  • 1
  • 29
  • 61
  • 2
    You could create overloads for the method that take in any number of expected parameters. – Ron Beyer Nov 13 '15 at 16:14
  • Yes, I could make `Method` take T and int but how will it create `Foo`? `Foo` is not known to the method. Suppose that `Method` is in another library. – wingerse Nov 13 '15 at 16:19
  • No, what I mean is create another `Method(Func del)` that would overload the other one, that way you could call it with either one. As it is you can't make the existing one accept a `Func` because it expects a `Func`. – Ron Beyer Nov 13 '15 at 16:22
  • No. What I want is that `del` should be in the form `x => new Foo(x)` so that I can ensure that `Foo` has a constructor taking a parameter of type int, as there is no generic constraint like that. – wingerse Nov 13 '15 at 16:26
  • I think you may need to expand on what you are asking about, from your question it seems you want to be able to call `Method` with two different types of lambda's, however from the comments it seems maybe you are wanting to restrict it to only accept a certain type, is that right? The only way to do that is to create an overload for each expected type, ie `Method(Func del)` and `Method(Func del) etc for each type. You can't create a list of generic constraints or constrain to a specific type. – Ron Beyer Nov 13 '15 at 16:29
  • I have edited my question. Hope its clear now :) I want my delegate/lambda to take an int and return a `SomeType` *whose constructor must take that int* – wingerse Nov 13 '15 at 16:36
  • So why not just use `Method(Func del)` and drop the generic completely? – Ron Beyer Nov 13 '15 at 16:37
  • Augh, I don't want the func to return an int. It should return the `SomeType` which I pass as the generic argument. Lets just leave the `Method` and focus on the `Func`. It should accept an int and return a `T`. And the `T` should have a constructor taking an int. The main goal is calling `T(something)` also ensuring that `T` actually can do it without throwing a runtime exception.. But it's not possible with C# generics at the moment. – wingerse Nov 13 '15 at 16:40

1 Answers1

0

You don't need a func to do this. Just pass in the type you want and it will return the object and ensure the int gets passed into it. You're then basically just creating a factory method that will give you the type you want with the integer passed in.

public T Method<T>(int whatever) where T : class
{
     return (T)Activator.CreateInstance(typeof(T), whatever);
}

var type = Method<SomeType>(55);
Stephen Brickner
  • 2,584
  • 1
  • 11
  • 19
  • That is not possible. You can't call `T()` with parameters. This gives a compiler error "'T': cannot provide arguments when creating an instance of a variable type" – wingerse Nov 13 '15 at 16:49
  • This again violates the purpose of the workaround in the question I linked. It I do that, how can I ensure that `T` will have a constructor taking an int? If it didn't this `Method` will throw some kind of runtime exception. Of course I can be careful while coding but I want to use generics to enforce the rules. – wingerse Nov 13 '15 at 16:52
  • 1
    Ok I understand what you are trying to do now. There is no way to ensure T has a constructor taking an int without either using reflection to check it first or create a new one like in my example and try to invoke it. In either case even done in a func like you are wanting there is a possibility for an exception if the type you pass in doesn't take a constructor param. It's a good question though. – Stephen Brickner Nov 13 '15 at 16:58
  • Thanks. Then I will just use reflection and throw an exception if it doesn't have the constructor taking an int. :) – wingerse Nov 13 '15 at 17:02