My question is a bit similar to this one: How to convert an action to a defined delegate of the same signature?
Why there is no implicit convertion between delegates with same signature. For example, code:
class Program
{
private delegate void Foo1(int x);
private delegate void Foo2(int x);
static void Main(string[] args)
{
Foo1 foo1 = Console.WriteLine;
Foo2 foo2 = Console.WriteLine;
Call(foo1);
Call2(foo2);
}
static void Call(Action<int> action)
{
action(10);
}
static void Call2(Foo1 action)
{
action(10);
}
}
it does not compile because there isn't implicit convertion from Action<int> to Foo1.
But normaly it's the same thing. So it mean this names are aliases, not actualy names. So i think it was great idea to think about it like aliases. So in this case we have 3 aliases of a delegate, that get one int value and returns nothing. And this delegates are fully interchangeable one by another. But we don't have it. So question is: why? By signatures it's the same thing, and there isn't any implementation, so delegates with same signature are one and same with many aliases...
Is it C# defect or there are reasons for it? As to me, i don't see any.
There's no implicit conversion between those two delegates for the same reason that there's no implicit conversion between these two types:
public sealed class Foo1
{
public string Value { get; set; }
}
public sealed class Foo2
{
public string Value { get; set; }
}
Just because two classes have the same fields doesn't mean that you should be able to treat one as if it were another. The same logic applies to delegates (which are also types, mind you).
There is semantic meaning applied to the creation of that type. If someone created a Foo1 they want it to be a Foo1, not a Foo2. If they're going out of their way to use a Foo1 where a Foo2 is expected, it's a big red flag that even though the types appear similar, there is a semantic difference between these two types. If the programmer knows something that the compiler doesn't, they can use an explicit conversion of some sort to indicate that they know what they're doing.
(The previous paragraph was intentionally written to apply equally to your delegates, and the classes I provided above.)
Related
Suppose that my namespace has 2 delegates:
public delegate void D1(string s);
public delegate void D2(string s);
They are implemented in a static class StClass like this:
public static D1 myD1 { get; set; }
public static D2 myD2 { get; set; }
In each instance of a separate non-static class MyClass I would like to include a delegate that points to one of the 2 static delegates as determined by the constructor. So I would have:
public class MyClass
{
public delegate void D(string s);
public D myD { get; set; }
public MyClass()
{
if()
{
myD = StClass.myD1 //this assignment won't work
}
else
{
myD = StClass.myD2
}
}
I get that I cannot directly link myD to myD1 or myD2 the way it's shown above because from the compiler's standpoint they are instances of different delegate types, but I figure since they all share the same signature there should be a simple way to achieve this. What am I missing?
As per comments, it would probably be better to avoid declaring multiple delegate types with the same signature like this.
However, if you absolutely have to, you can convert them like this:
myD = new D(StClass.myD1);
Note that this uses the value of StClass.myD1 at the time of assignment. If you want to dynamically observe any changes in StClass.myD1, you could use a lambda expression instead:
myD = s => StClass.myD1(s);
This will evaluate the StClass.myD1 property on each invocation.
You start by saying "Suppose that my namespace has 2 delegates:"
public delegate void D1(string s);
public delegate void D2(string s);
But, that's not what you are showing. You are showing the declaration of two, different Delegate Types. You still haven't declared a delegate yet.
Then, within your class, you declare a third delegate type, and an instance of that type:
public delegate void D(string s);
public D myD { get; set; }
Now you start trying to assign delegates of one type to another. That's never going to work; two delegate types, even if their definition completely agrees, remain distinct types. Somewhere, #EricLippert has a blog entry that explains this in detail (but, after a quick search, I can't find it). The pair of types that show this that most C# programmers are familiar with (and curse at) are:
delegate bool Predicate<in T>(T obj);
and
Func<T, bool>
The latter is used for the IEnumerable<T>.Where() extension method, while the former is used in methods like List<T>.FindAll(). Grrrr
The solution, as others have pointed out, is to use a single delegate type. Both the generic Action and Func delegates have been around for nearly forever now. I rarely define delegate types anymore, instead relying on those two types.
I have a class that overrides the addition operator twice. One that takes the type parameter and one that takes a double:
public class A<T>
{
public A() { }
public static A<T> operator +(A<T> a, T t)
{
Console.WriteLine("Generic add called.");
return new A<T>(); // return to keep the compiler happy
}
public static A<T> operator +(A<T> a, double d)
{
Console.WriteLine("Double add called.");
return new A<T>(); // return to keep the compiler happy
}
}
When the class is parameterized by the int type, it behaves as expected:
A<int> aInt = new A<int>();
var test = aInt + 3;
// -> Generic add called.
test = aInt + 3.0;
// -> Double add called.
But when parameterized by the double type, the non-generic add is called:
A<double> aDouble = new A<double>();
var otherTest = aDouble + 3.0;
// -> Double add called.
Assuming this behavior is the norm, I know which will be called. The non-generic override will be preferred. That said...
Will the non-generic method be always be preferred in the event of a collision?
All of the above code is available, runnable in your browser, here
EDIT: This question is related, but it's asking about generic methods, not classes. He gives this code:
class A
{
public static void MyMethod<T>(T myVal) { }
public static void MyMethod(int myVal) { }
}
which does not apply to my usage examples. Distinguishing between a.MyMethod(3) and a.MyMethod<int>(3) is obvious - one is generic and one is not.
The more specific method will be chosen, but that construction is a bad idea because it is technically unspecified behaviour.
To quote #EricLippert, substituting the code snippets for the ones from my question:
But the situation with [aDouble + 3.0] is far worse. The CLR rules make this sort of situation "implementation defined behaviour" and therefore any old thing can happen. Technically, the CLR could refuse to verify a program that constructs type [A<double>]. Or it could crash. In point of fact it does neither; it does the best it can with the bad situation.
Are there any examples of this sort of type construction causing truly implementation-defined behaviour?
Yes. See these articles for details:
http://blogs.msdn.com/b/ericlippert/archive/2006/04/05/odious-ambiguous-overloads-part-one.aspx
http://blogs.msdn.com/b/ericlippert/archive/2006/04/06/odious-ambiguous-overloads-part-two.aspx
Simple answering yes. The compiler assume that because you have treated by hand a particular type parameter, that means that it has some special logic for you. That's why the second operator is called. To say further, operators are nothing more than static methods that accepts some parameters. For your case it's a binary operator so the static method has two parameters.
I write this piece of code in one of my C# project:
public static class GetAppendReceiver
{
public static AppendReceiver<DataType> Get<DataType>(AppendReceiver<DataType>.DataProcessor processor0, int delayIn = 0)
{
throw new InvalidOperationException();
}
public static AppendReceiver<string> Get(AppendReceiver<string>.DataProcessor processor0, int delayIn = 0)
{
return new StringAppendReceiver(processor0, delayIn);
}
}
public abstract class AppendReceiver<DataType>
{
public delegate void DataProcessor(DataType data);
...
}
AppendReceiver<DataType> is an Abstract class, DataProcessor is a delegate type.
When calling GetAppendReceiver.Get with a string DataProcessor I expect the overloaded function to be called, but I get the InvalidOperationException.
Here is my call:
class ClassA<DataType>
{
public void RegisterAppendReceiver(AppendReceiver<DataType>.DataProcessor receiver)
{
appendReceivers.Add(GetAppendReceiver.Get(receiver, Delay));
}
}
Example of RegisterAppendReceiver call:
myObject.RegisterAppendReceiver(myMethod);
Where myMethod is defined like this:
public void writeMessage(string strMessageIn)
My question is why I get the wrong overload called, and how can I force the language to call the overload I want ?
Thanks for your help !
Eric Lippert answers this question concisely in his article Generics are not Templates
I don't want to copy the entire article. So the relevant point is this:
We do the overload resolution once and bake in the result.
So the C# compiler decides, at the time it compiles RegisterAppendReceiver, which overload of "GetAppendReceiver.Get" it is going to call. Since, at that point, the only thing it knows about DataType is that DataType can be anything at all, it compiles in the call to the overload that takes an AppendReceiver.DataProcessor, not an AppendReceiver.DataProcessor.
By comparison, the C++ compiler does not behave this way. Each and every time a generic call is made, the compiler does the substitution over again. This is one reason C++ compilers are much slower than C# compilers.
I have the following simple code
abstract class A
{
public abstract void Test(Int32 value);
}
class B : A
{
public override void Test(Int32 value)
{
Console.WriteLine("Int32");
}
public void Test(Double value)
{
Test((Int32)1);
}
}
When I ran this code the line Test((Int32)1) causes stack overflow due to infinite recursion. The only possible way to correctly call proper method (with integer parameter) I found is
(this as A).Test(1);
But this is not appropriate for me, because both methods Test are public and I am willing the users to be able to call both method?
Method overload resolution in C# does not always behave as you might expect, but your code is behaving according to the specification (I wrote a blog post about this a while ago).
In short, the compiler start off by finding methods that
Has the same name (in your case Test)
are declared in the type (in your case B) or one of its base types
are not declared with the override modifier
Note that last point. This is actually logical, since virtual methods are resolved in run-time, not compile time.
Finally, if the type (in this case B) has a method that is a candidate (which means that the parameters in your call can be implicitly converted to the parameter type of the candidate method), that method will be used. Your overridden method is not even part of the decision process.
If you want to call your overridden method, you will need to cast the object to its base type first.
Unfortunately in order to call the A::Test(int) through a B reference some sort of cast is needed. So long as the C# compiler sees the reference through B it will pick the B::Test(double) version.
A slightly less ugly version is the following
((A)this).Test(1);
Another thought though is have a private method with a different name that both feed into.
class B : A {
public override void Test(int i) {
TestCore(i);
}
public void Test(double d) {
TestCore(1);
}
private void TestCore(int i) {
// Combined logic here
}
}
I'm trying to do some unit testing on a project that unfortunately has high level of unit interdependence. Currently, a lot of our classes look to a custom UserIdentity object to determine authentication, but that object has a lot of internal hoop-jumping that I would just as soon avoid when trying to test individual unit functionality.
To work around some of this, I'm trying to create a "mock" version of this UserIdentity that can be plugged in with a more tightly-controlled variable environment.
Long story short, we have a UserIdentity class with several public read-only properties and a static CurrentIdentity (IIdentity) placeholder. I'm able work around just about everything with a "mock" IIdentity implementation, but I'm running into a wall when I reach a point where the CurrentIdentity is cast as a UserIdentity.
It's a pretty straight-forward method:
internal static UserIdentity GetCurrentIdentity()
{
UserIdentity currentIdentity = ApplicationContext.User.Identity as UserIdentity;
return currentIdentity;
}
I've set up my mock object to create a member of the UserIdentity type, and then do something like this:
public static implicit operator UserIdentity(MockUserIdentity src)
{
return src.UserIdentity;
}
or this
public static explicit operator UserIdentity(MockUserIdentity src)
{
return src.UserIdentity;
}
The problem is that as far as I can tell, that 'as' doesn't seem to invoke either an implicit or explicit conversion operation on my mock object. My question(s) is(are?), am I missing something simple here or will this not work because (I'm guessing) the 'as' operation looks directly to class inheritance (which my object does not do...)?
Also, a bit off topic maybe, but why can there not be simultaneous explicit and implicit operators of the same resultant type within a class? Unless I'm missing something silly, the compiler balks if I try to have both conversion operators at once. I have to pick one or the other.
UPDATE
Okay, now I'm thoroughly confused. Maybe I'm getting sloppy, but I've tried doing the direct cast, and I can't seem to get that to work either. I read up on the operator at MSDN, and the example shows the operator going in the resultant class rather than the source class, but I'm not sure if that matters or not (I tried both places in the code below). Either way, I tried to set up a simple test bed to see what I might be doing wrong, but I can't get that to work either...Here's what I've got
class Program
{
// Shared Interface
public interface IIdentity { }
// "real" class (not conducive to inheritence)
public class CoreIdentity : IIdentity
{
internal CoreIdentity() { }
// Just in case (if this has to be here, that seems unfortunate)
public static explicit operator CoreIdentity(ExtendedIdentity src)
{
return src.Identity;
}
}
// "mock" class (Wraps core object)
public class ExtendedIdentity : IIdentity
{
public CoreIdentity Identity { get; set; }
public ExtendedIdentity()
{
Identity = new CoreIdentity();
}
// This is where the operator seems like it should belong...
public static explicit operator CoreIdentity(ExtendedIdentity src)
{
return src.Identity;
}
}
// Dummy class to obtain "current core identity"
public class Foo
{
public IIdentity Identity { get; set; }
public CoreIdentity GetCoreIdentity()
{
return (CoreIdentity)Identity;
}
}
static void Main(string[] args)
{
ExtendedIdentity identity = new ExtendedIdentity();
Foo foo = new Foo();
foo.Identity = identity;
CoreIdentity core = foo.GetCoreIdentity();
}
}
But that throws the following exception when I invoke foo.GetCoreIdentity():
Unable to cast object of type 'ExtendedIdentity' to type 'CoreIdentity'.
and I can't catch either of my explicit operators with a break point, so it looks like it's making this determination without even "trying" the conversion routes I've provided.
Surely I'm missing something obvious. Does the fact that I have my Identity (in Foo) defined as IIdentity somehow prevent resolution of the cast using the explicit operators of the implementing type? That would strike me as odd.
UPDATE (#2)
I feel like I'm spamming my post with all these updates (maybe I should get my act together before being so trigger-happy :) ) Anyway, I modified my Foo's GetCoreIdentityMethod to do this instead:
public CoreIdentity GetCoreIdentity()
{
ExtendedIdentity exId = Identity as ExtendedIdentity;
if (exId != null)
return (CoreIdentity)exId;
return (CoreIdentity)Identity;
}
and (after having to clean up the ambiguous reference caused by having the operator in both classes), it did step into my explicit conversion operator code, and it did work as expected. So I guess it looks like the explicit operators are not resolved polymorphically (is that the correct understanding?), and the fact that my property was typed as an IIdentity rather than an ExtendedIdentity prevented it from invoking the cast logic even though it was of the ExtendedIdentity type at the time it was invoked. That strikes me as very peculiar and unexpected....and kind of unfortunate.
I don't want to have to re-write the keeper of the CurrentIdentity object to make it aware of my special test cast mocks. I wanted to encapsulate that "special" logic into the mock itself, so this really throws me for a loop.
Does the fact that I have my Identity
(in Foo) defined as IIdentity somehow
prevent resolution of the cast using
the explicit operators of the
implementing type?
Here's a hint: how do you define an explicit (or implicit, for that matter) conversion operator? (I know you know this since you already did it; I am asking the question to illustrate a point.)
public static explicit operator UserIdentity(MockUserIdentity src)
{
return src.UserIdentity;
}
There's something very important to realize here. The C# designers made the wise choice of making all operators static. So the explicit operator defined above translates to essentially a static method call looking something like this:
public static UserIdentity op_Explicit(MockUserIdentity src)
{
return src.UserIdentity;
}
Now, here is what I'm getting at. The behavior that perplexed you in your question because it seemed to fail in the polymorphism department was really the result of C#'s system of method overload resolution.
If I have two methods:
void Write(string s) { Console.WriteLine("string"); }
void Write(object o) { Console.WriteLine("object"); }
...and then I have this program:
object x = "Hello!";
Write(x);
What will the output be?
The answer is "object" because the Write(object) overload was selected by the compiler -- as well it should have been. Write is not an instance method to be overridden by some derived type according to normal polymorphism; it is a static method, with overloads between which the compiler must make a choice. Since x in the above code is declared to be of type object, that choice is unambiguously Write(object).
So in the case of your code, where you have this:
public IIdentity Identity { get; set; }
public CoreIdentity GetCoreIdentity()
{
return (CoreIdentity)Identity;
}
The compiler must investigate: is there an op_Explicit overload which accepts an IIdentity parameter? No, there is not. There's one that accepts a UserIdentity parameter, but that's too specific (just as Write(string) was too specific for x in the example above).
So the reason your explicit operator was not called in your initial tests was that the compiler will not resolve (CoreIdentity)Identity to that particular overload. This is also why your modified version does work:
public CoreIdentity GetCoreIdentity()
{
ExtendedIdentity exId = Identity as ExtendedIdentity;
if (exId != null)
{
// Since exId is actually declared to be of type ExtendedIdentity,
// the compiler can choose the operator overload accepting
// an ExtendedIdentity parameter -- so this will work.
return (CoreIdentity)exId;
}
return (CoreIdentity)Identity;
}
as does not invoke conversion operators. See: http://msdn.microsoft.com/en-us/library/cscsdfbt(v=VS.100).aspx
Use a (cast).
So, why don't you use an explicit cast?
// will throw if cast fails
internal static UserIdentity GetCurrentIdentity()
{
UserIdentity currentIdentity = (UserIdentity) ApplicationContext.User.Identity ;
return currentIdentity;
}
This ought to trigger your explicit operator. You can test with is first to make it safer.
As mentioned by Ray as doesn't invoke the conversion operators.
That said, you should be using an explicit cast in that type of scenarios.
That way, You get very clear information when something isn't set up right and the object at ApplicationContext.User.Identity wasn't what the code expected it to.