Delegates with output type return (C #)

I'm still new to delegates, and I'm playing at the delegate-based data access level described in Stephen John Metker's book "Template Design in C #" (great reading!). It defines the data access delegate as follows:

public delegate object BorrowReader(IDataReader reader); 

The result of using this code is one of the following:

 var result = Foo.Bar(new BorrowReader(DoFooBarMagic)); var result = Foo.Bar(DoFooBarMagic); 

However, since the return type of the delegate is an β€œobject”, you need to drop it to get what the method (DoFooBarMagic in this example) really returns. Therefore, if "DoFooBarMagic" returns a List, you need to do something like this:

 var result = Foo.Bar(DoFooBarMagic) as List<string>; 

I would like you to skip the broadcast and get the delegate return type from the delegate method return type. My thought was maybe a way to use the type parameter to output the return type. Something like one of them:

 public delegate T BorrowReader<T>(IDataReader reader); List<string> result = Foo.Bar(new BorrowReader(DoFooBarMagic)); //Look, Ma, no cast! var result2 = Foo.Bar(DoFooBarMagic); 

If the return type is inferred from the return type of the delegate method, but it does not work. Instead, you should do this:

 public delegate T BorrowReader<T>(IDataReader reader); var result = Foo.Bar(new BorrowReader<List<string>>(DoFooBarMagic)); 

It hardly looks better than a cast.

So, is there a way to infer the return type of the delegate from the return type of the delegate method?

Edit to add: I can change the signature of Foo.Bar if necessary. The current signature is essentially this:

 public static T Bar<T>(string sprocName, DbParameter[] params, BorrowReader<T> borrower); 

Note: this signature is the result of the current state that this delegate definition uses:

 public delegate T BorrowReader<T>(IDataReader reader); 
+4
source share
6 answers

What about:

 public static T Bar2<T>(Func<IDataReader,T> func) where T : class { BorrowReader borrower = new BorrowReader(func); return (T) Foo.Bar(borrower); } 

I know that he still does an acting show, which is ugly, but it should work. (I initially thought you could get away with the implicit conversion from func , but apparently not. At least not until C # 4.0.)

Of course, if you can change the signature of Foo.Bar to general, you laugh ...

EDIT: to respond to a comment: if the method signature is changed to accept a common delegate, e.g.

 public static T Bar<T>(Func<IDataReader, T> func) 

then the calling code could almost be:

 var result = Foo.Bar(DoFooBarMagic); 

Unfortunately, type inference does not work with method groups, so you should use either:

 Func<IDataReader, List<string>> func = DoFooBarMagic; var result = Foo.Bar(func); 

or (better if a little less effective)

 var result = Foo.Bar(reader => DoFooBarMagic(reader)); 

So, you are right - this answer did not quite bring the OP to what was required, but apparently it came close enough to get recognition. Hope this change helps explain the rest :)

+6
source

This is ugly, but you can use the out parameter. From my enum parser:

 public static T Parse<T>(string value) { // return a value of type T } public static void Parse<T>(string value, out T eValue) { // do something and set the out parameter } // now can be called via either SomeEnum blah = Enums.Parse<SomeEnum>("blah"); // OR SomeEnum blah; Enums.Parse("blah", out blah); 

The second deduces the type, but, as I said, it is ugly.

0
source

Do not use generics. Type inference is a compile-time event. One solution would be to have a common delegate that you posted. A general delegate will be faster than casting.

0
source

I don’t think there is a way around this. At least not the way you suggest it. The main problem is that since it must be inferred at compile time, unless you have an explicit return type, the compiler cannot actually infer the type of the return value.

0
source
 // if BorrowReader is generic... public delegate T BorrowReader<T>(IDataReader reader); public class Foo { // ... and Foo.Bar() is also generic public static T Bar<T>(BorrowReader<T> borrower) { ... } public void SomeMethod() { // this does *not* work (compiler needs more help) var result1 = Foo.Bar(DoFooBarMagic); // but instead of this (which works) var result2 = Foo.Bar(new BorrowReader<List<string>>(DoFooBarMagic)); // you can do this (also works) // which emits the same IL, anyway var result3 = Foo.Bar<List<string>>(DoFooBarMagic); } } 
0
source

I expect F # to be able to do this. I'm not an expert, but F # uses type inference of return type ( details on MSDN ).

0
source

All Articles