Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
317 views
in Technique[技术] by (71.8m points)

c# - Generic overload resolution

I have the following scenario:

class Foo { }

class Foo<T> : Foo { }

And then two methods

void DoStuff(Foo foo) 
{
     DoStuffImpl(foo);
}

void DoStuffImpl(Foo foo) 
{ 
     Console.WriteLine("A");
}    
void DoStuffImpl<T>(Foo<T> foo) 
{ 
     Console.WriteLine("B");
} 

void Main() 
{
     DoStuff(new Foo<int>()); // prints A
}

(note, the code was written in the browser, but describes the situation I'm facing)

How can I get it to call the generic method, and print B?

Can this be done at all without reflection? I have some ideas on how it could be done with reflection, but I'm looking for a cleaner solution if one exists.

Note: I can't make DoStuff generic because this will be used with WCF and open generic types are not allowed.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

(I assume you already understand why this is happening. If not, read my overload resolution article and let me know if it's still unclear.)

If you're using C# 4 you could use dynamic typing:

void DoStuff(Foo foo) 
{
    dynamic d = foo;
    DoStuffImpl(d);
}

Note how this doesn't just have a dynamic parameter - the idea is that by restricting foo to be of type Foo or a subclass, we'll always have a valid DoStuffImpl to call... it's just that the best method will be determined at execution time, not compile time.

If you're stuck in pre-C# 4, you could potentially do it with double dispatch:

class Foo
{
    public virtual void CallStuffImpl(FooImplType x)
    {
        x.DoStuffImpl(this);
    }
}

class Foo<T> : Foo
{
    public override void CallStuffImpl(FooImplType x)
    {
        // Looks like it's redundant, but isn't! "this" is
        // known to be Foo<T> rather than Foo
        x.DoStuffImpl(this);
    }
}

Then:

void DoStuff(Foo foo) 
{
    foo.CallStuffImpl(this); // Let it dispatch appropriately
}

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...