Ayende @ Rahien

Hi!
My name is Oren Eini
Founder of Hibernating Rhinos LTD and RavenDB.
You can reach me by phone or email:

ayende@ayende.com

+972 52-548-6969

, @ Q c

Posts: 18 | Comments: 79

filter by tags archive

Csc.exe and delegate inference, or: Why C# has awkward syntax

time to read 2 min | 212 words

I just tried to to do a major revamp of Rhino Mocks' interface. It was intended to make it easier to work with C# 3.0 and use the smarter compiler to get better syntax.

I shouldn't have bothered. Take a look at this.

	public class TestCsc
	{
		public static void TestMethod()
		{
			Execute(Bar); // fail to compile
			Execute(delegate(int ia, string x) { }); // compiles fine
			Execute((int i, string x) => { return; }); // Compiles fine
			Execute((int i, string x) => { return true; }); // fail to compile
			Execute(Foo);// fail to compile
			Execute(delegate(int ia, string x) { return true; }); // fail to compile
		}

		public static bool Foo(int ia, string x)
		{
			return false;
		}

		public static void Bar(int ia, string x)
		{
		}

		public static void Execute<T, K>(Action<T, K> e)
		{
			
		}

		public static void Execute<T, K>(Func<bool, T, K> e)
		{

		}
	}
Annoyed.

Comments

Jay
Jay

Maybe you were looking for Func<T, K, bool>?

ychebotarev

public static void Execute<T, K>(Func<bool, T, K> e)

should be

public static void Execute<T, K>(Func<T, K,bool> e)

:)

after that there will be errors only with

Execute(Bar);

Execute(Foo);

you can rewrite this as

        Action<int, string> bar_ptr = Bar;

        Execute(bar_ptr); // compiles fine

        Func<int, string, bool> foo_ptr = Foo;

        Execute(foo_ptr);// compiles fine

Here is big explanation why type inference didn't work in this case:

http://blogs.msdn.com/ericlippert/archive/2007/11/05/c-3-0-return-type-inference-does-not-work-on-member-groups.aspx

But for me that was not very convincing.

Steve

Lambda stuff is nice but I would love to see Boo DSL for rhino mocks :)

Frans Bouma

Yes, this is pretty annoying. I ran into this as well when I wanted to introduce some types for prefetchpath specifications inside linq queries and wanted to get rid of the explicit generic argument specifications... IMHO it's a compiler flaw, no matter how many excuses they invent: they introduced syntactic sugar, then make the compiler deal with that in all cases.

Justin Etheredge

If you swap the bool on the end to Func<T, K, bool> then everything except for Execute(Bar) and Execute(Foo) works. And I agree with Frans, I have heard all the explanations about why it wouldn't work, but I wish they could have found a way to make it work.

Justin Etheredge

Let me also say that they could have enabled this for very simple scenarios such as the one you are dealing with. In the blog post by Eric Lippert referenced above he basically says that they could have done it in certain scenarios, but in other scenarios it would have been impossible. He said that they didn't want two different inference algorithms that produce slightly different results. While I am certainly not a compiler writer, that sounds like they are taking an idealistic approach and not a pragmatic one. The pragmatic approach would have been to try and make type inference work in as many different scenarios as possible, and have it fail when the resolution is unreachable.

Jay
Jay

Execute((t, k) => Bar(t, k));

Execute((t, k) => Foo(t, k));

Krzysztof Koźmic

I now your pain, earlier this week, I've been trying to come up with nicer, and more strongly typed ways to cope with events in Rhino.Mocks (strongly typed EventRaiser, event subscribtion and verification) and I failed miserably. I think I just gave up (at least for now). You can see the attempts at my blog.

And BTW, why are delegates so limited in cooperation with generics? :/ It's just annoying

Comment preview

Comments have been closed on this topic.

FUTURE POSTS

  1. Production postmortem: The industry at large - 11 hours from now
  2. The insidious cost of allocations - about one day from now
  3. Buffer allocation strategies: A possible solution - 4 days from now
  4. Buffer allocation strategies: Explaining the solution - 5 days from now
  5. Buffer allocation strategies: Bad usage patterns - 6 days from now

And 2 more posts are pending...

There are posts all the way to Sep 11, 2015

RECENT SERIES

  1. Find the bug (5):
    20 Apr 2011 - Why do I get a Null Reference Exception?
  2. Production postmortem (10):
    01 Sep 2015 - The case of the lying configuration file
  3. What is new in RavenDB 3.5 (7):
    12 Aug 2015 - Monitoring support
  4. Career planning (6):
    24 Jul 2015 - The immortal choices aren't
View all series

Syndication

Main feed Feed Stats
Comments feed   Comments Feed Stats