Assume I have a class C that inherits from 2 interfaces (I1 and I2). I also have two versions of a method (DoStuff), each taking one of the interfaces as a parameter. If I call DoStuff(C), which one gets called?
interface I1 { ... }
interface I2 { ... }
class C : I1, I2 { ... }
int DoStuff(I1 target) { ... }
int DoStuff(I2 target) { ... }
//What gets called here?
C target = new C()
DoStuff(target)
If I2 derives from I1, I think it's relatively simple - the I2 version gets called. I'm interested in the case where the interfaces are independent.
Assume I can't edit C, I1 or I2. And .NET 2.0 if that makes any difference.
Neither gets called. If your two methods are overloads in the same class, the compiler does not attempt to disambiguate at all. It'll simply not compile your code, saying it's ambiguous between your two overloads as you declared target to be a type that implements both interfaces.
If you declare target to be of one of the interface types, or cast it at call-time (as Jon shows), then there's no ambiguity.
As BoltClock says, it won't compile. However, it's easy to make it do what you want: just use an expression of the type that you want to use for the argument. For example:
C target = new C();
DoStuff((I1) target);
or
C target = new C();
I1 i1 = target;
DoStuff(i1);
Basically without any extra work, the overload resolution steps will find both methods in the candidate set, and determine that neither is "better" than the other, so overload resolution will fail.
There will be an error when you try to compile it:
error CS0121: The call is ambiguous between the following methods or properties: 'DoStuff(I1)' and 'DoStuff(I2)'"
Related
I am converting a Java project to C# and i am getting in trouble with the following:
IMessageHandler
public interface IMessageHandler<T, H> where T : IPeerAttachment where H : IMessage {
void HandleMessage(T clientAttachment, H message);
}
LoginRequestHandler
public class LoginRequestHandler : IMessageHandler<LoginPeerAttachment , LoginRequest> {
public void HandleMessage(LoginPeerAttachment clientAttachment, LoginRequest message) {
}
}
MessageHandlerRegistry
private readonly Dictionary<MessageId, IMessageHandler<IPeerAttachment, IMessage>> _handlers = new Dictionary<MessageId, IMessageHandler<IPeerAttachment, IMessage>>();
What i would like to do is following:
LoginRequestHandler loginRequestHandler = new LoginRequestHandler();
_handlers[messageId] = loginRequestHandler;
This gives me an compile error telling me that it need to be of type IMessageHandler.
I am not sure why this do not work since LoginRequestHandler implements only derived types of what is specified in interface.
Any suggestion how to solve this?
Ok, this is disallowed because its not type safe. Huh? How can the following not be type safe:
var _handlers = new Dictionary<MessageId, IMessageHandler<IPeerAttachment, IMessage>>();
var loginRequestHandler = new LoginRequestHandler();
_handlers[messageId] = loginRequestHandler;
LoginRequestHandler is a IMessageHandler<IPeerAttachment, IMessage> so what is wrong here?
Well, lets say the previous were legal, and take it a step further and see what happens:
var handler = _handlers[meesageId];
handler.HandleMessage(logOutPeerAttachment, logOutMessage);
Is that legal? Well, it sure looks like it. handler is of type IMessageHandler<IPeerAttachment, IMessage> and therefore HandleMessage can handle the supplied argument types...
So, now we've come to a horrible situation; following perfectly legal steps, we've just broken the type system because somehow we've asked a LoginRequestHandler to handle a LogOutRequest.
Obviously, as you've painfully experienced first hand, not all steps are legal; this reference conversion is in fact illegal: (IMessageHandler<IPeerAttachment, IMessage>)loginRequestHandler
In order for this conversion to work, the type variance of IMessageHandler would need to be covariant which means, generic arguments can only go out, not in (its a bit more convoluted than that but it gets the idea across). Canonical example? IEnumerable<out T>? Why? Because there is no way to input a T in an IEnumerable<T> , therefore this is legal:
var tigers = new List<Tiger>();
IEnumerable<Animal> animals = tigers;
But this isn't:
var tigers = new List<Tiger>();
List<Animal> animals = tigers;
In your scenario, a covariant interface doesn't seem to be a choice so you probably need to reconsider your approach. You seem to be trying to express too much in your type system to the point that's its fighting against you.
What you're trying to do is fundamentally incompatible with a type system that isn't unsound with respect to generic variance like the Java type system is.
If you were able to assign a LoginRequestHandler to a variable of type IMessageHandler<IPeerAttachment, IMessage> then you would be able to call the HandleMessage method with any types derived from IPeerAttachment and IMessage, thus causing a runtime error.
I'm creating a type at runtime using Reflection.Emit. The problem is that whenever I instantiate an instance of the new type I have to use object or dynamic because the type isn't known at compile time. This works fine except for when I would want another type to implicitly cast to the new type during assignment. The variable happily takes on the new value and it's corresponding type without attempting to cast to its current type.
Is there any way to create a variable of a newly created type that will allow for implicit casting? I'm perfectly happy to give up compile-time checking but I would like these casts to at least be attempted at run-time.
Edit:
Here is an example to make it more clear. This is what happens when you know the type at compile-time:
MyClass a;
//this calls the implicit cast operator and 'a' stays of the same type
a = 5;
and this is what happens if you don't:
Type t = CreateTypeUsingTypeBuilder();
object a = Activator.CreateInstance(t);
//this does not call the implicit cast operator and 'a' just becomes in integer
a = 5;
Also, I'm not surprised at this behavior or asking why it happens. I'm asking if there is any sort of workaround to achieve the desired behavior of having it check for an implicit operator at run-time.
In order to understand why this is not possible, at least not directly, one needs to understand how implicit conversion operators work in the first place.
When you write something like this
MyNumericType x = new MyNumericType(123);
double y = x;
the compiler realizes that x and y are of different types, and searches MyNumericType to see if there is an implicit conversion operator defined:
public static implicit operator double(MyNumericType n) {
return n.doubleValue;
}
Once the operator is found, the compiler invokes it as if it were a regular static method (which it is).
When you work with types generated at runtime, you should generate the conversion at runtime as well. For example, if you do this
private static Func<object,object> MakeConverter(Type t1, Type t2) {
var p = Expression.Parameter*(typeof(object));
var eFrom = Expression.Convert(p, t1);
var eTo = Expression.Convert(eFrom, t2);
var res = Expression.Convert(eTo, typeof(object));
var lambda = Expression.Lambda<Func<object,object>>(res, new[] { p });
return (Func<object,object>)lambda.Compile();
}
With this method in place you can do this:
Type runtimeType1 = ...
Type runtimeType2 = ...
var converter = MakeConverter(runtimeType1, runtimeType2);
object objRuntimeType1 = ...
object objRuntimeType2 = converter(objRuntimeType1);
If the idea is, as I suppose in this context, to create wrapper classes for known types in runtime, then I have a few ideas you could try.
One is to add a parameterized constructor in the wrapper type, that takes an object of the wrapped type as the parameter and then uses that object to initialize the wrapper object (like you would do in an implicit conversion operator). Then, knowing that you can use e.g. an integer as a constructor parameter, you could simply do this:
Type t = CreateTypeUsingTypeBuilder();
object a = Activator.CreateInstance(t, 5);
This will search the type for a constructor that could be invoked with the given object. You might get MissingMethodException if no matching public constructor is found.
Another idea is to create either an interface or an abstract base type for your types built in runtime, that requires the derived classes to implement some sort of conversion method. When you derive your built types from this abstract class or make them implement the interface, you can cast the object created with the Activator to that class or that interface and then call the conversion method already normally. If you make your interface generic, you could have multiple different conversion implementations.
public interface IMyWrapper<T>
{
IMyWrapper<T> Convert(T value);
}
While there is no way to use an implicit operator implicitly, I think you could achieve your ultimate goal of converting an integer to your built type in some other way, including one or the other hinted above.
Take the following:
class A {}
class B : A {}
class C
{
C()
{
var b = new B();
Foo(b);
Foo2(ref b); // <= compile-time error:
// "The 'ref' argument doesn't match the parameter type"
}
void Foo(A a) {}
void Foo2(ref A a) {}
}
Why does the above compile-time error occur? This happens with both ref and out arguments.
=============
UPDATE: I used this answer as the basis for this blog entry:
Why do ref and out parameters not allow type variation?
See the blog page for more commentary on this issue. Thanks for the great question.
=============
Let's suppose you have classes Animal, Mammal, Reptile, Giraffe, Turtle and Tiger, with the obvious subclassing relationships.
Now suppose you have a method void M(ref Mammal m). M can both read and write m.
Can you pass a variable of type Animal to M?
No. That variable could contain a Turtle, but M will assume that it contains only Mammals. A Turtle is not a Mammal.
Conclusion 1: ref parameters cannot be made "bigger". (There are more animals than mammals, so the variable is getting "bigger" because it can contain more things.)
Can you pass a variable of type Giraffe to M?
No. M can write to m, and M might want to write a Tiger into m. Now you've put a Tiger into a variable which is actually of type Giraffe.
Conclusion 2: ref parameters cannot be made "smaller".
Now consider N(out Mammal n).
Can you pass a variable of type Giraffe to N?
No. N can write to n, and N might want to write a Tiger.
Conclusion 3: out parameters cannot be made "smaller".
Can you pass a variable of type Animal to N?
Hmm.
Well, why not? N cannot read from n, it can only write to it, right? You write a Tiger to a variable of type Animal and you're all set, right?
Wrong. The rule is not "N can only write to n".
The rules are, briefly:
1) N has to write to n before N returns normally. (If N throws, all bets are off.)
2) N has to write something to n before it reads something from n.
That permits this sequence of events:
Declare a field x of type Animal.
Pass x as an out parameter to N.
N writes a Tiger into n, which is an alias for x.
On another thread, someone writes a Turtle into x.
N attempts to read the contents of n, and discovers a Turtle in what it thinks is a variable of type Mammal.
Clearly we want to make that illegal.
Conclusion 4: out parameters cannot be made "larger".
Final conclusion: Neither ref nor out parameters may vary their types. To do otherwise is to break verifiable type safety.
If these issues in basic type theory interest you, consider reading my series on how covariance and contravariance work in C# 4.0.
Because in both cases you must be able to assign value to ref/out parameter.
If you try to pass b into Foo2 method as reference, and in Foo2 you try to assing a = new A(), this would be invalid.
Same reason you can't write:
B b = new A();
You're struggling with the classic OOP problem of covariance (and contravariance), see wikipedia: much as this fact may defy intuitive expectations, it's mathematically impossible to allow substitution of derived classes in lieu of base ones for mutable (assignable) arguments (and also containers whose items are assignable, for just the same reason) while still respecting Liskov's principle. Why that is so is sketched in the existing answers, and explored more deeply in these wiki articles and links therefrom.
OOP languages that appear to do so while remaining traditionally statically typesafe are "cheating" (inserting hidden dynamic type checks, or requiring compile-time examination of ALL sources to check); the fundamental choice is: either give up on this covariance and accept practitioners' puzzlement (as C# does here), or move to a dynamic typing approach (as the very first OOP language, Smalltalk, did), or move to immutable (single-assignment) data, like functional languages do (under immutability, you can support covariance, and also avoid other related puzzles such as the fact that you cannot have Square subclass Rectangle in a mutable-data world).
Consider:
class C : A {}
class B : A {}
void Foo2(ref A a) { a = new C(); }
B b = null;
Foo2(ref b);
It would violate type-safety
While the other responses have succinctly explained the reasoning behind this behavior, I think it's worth mentioning that if you really need to do something of this nature you can accomplish similar functionality by making Foo2 into a generic method, as such:
class A {}
class B : A {}
class C
{
C()
{
var b = new B();
Foo(b);
Foo2(ref b); // <= no compile error!
}
void Foo(A a) {}
void Foo2<AType> (ref AType a) where AType: A {}
}
Because giving Foo2 a ref B would result in a malformed object because Foo2 only knows how to fill A part of B.
Isn't that the compiler telling you it would like you to explicitly cast the object so that it can be sure you know what your intentions are?
Foo2(ref (A)b)
Makes sense from a safety perspective, but I would have preferred it if the compiler gave a warning instead of an error, since there are legitimate uses of polymoprhic objects passed by reference. e.g.
class Derp : interfaceX
{
int somevalue=0; //specified that this class contains somevalue by interfaceX
public Derp(int val)
{
somevalue = val;
}
}
void Foo(ref object obj){
int result = (interfaceX)obj.somevalue;
//do stuff to result variable... in my case data access
obj = Activator.CreateInstance(obj.GetType(), result);
}
main()
{
Derp x = new Derp();
Foo(ref Derp);
}
This won't compile, but would it work?
If you use practical examples for your types, you'll see it:
SqlConnection connection = new SqlConnection();
Foo(ref connection);
And now you have your function that takes the ancestor (i.e. Object):
void Foo2(ref Object connection) { }
What can possibly be wrong with that?
void Foo2(ref Object connection)
{
connection = new Bitmap();
}
You just managed to assign a Bitmap to your SqlConnection.
That's no good.
Try again with others:
SqlConnection conn = new SqlConnection();
Foo2(ref conn);
void Foo2(ref DbConnection connection)
{
conn = new OracleConnection();
}
You stuffed an OracleConnection over-top of your SqlConnection.
In my case my function accepted an object and I couldn't send in anything so I simply did
object bla = myVar;
Foo(ref bla);
And that works
My Foo is in VB.NET and it checks for type inside and does a lot of logic
I apologize if my answer is duplicate but others were too long
I am going through a book trying to understand Generics with C# and I have come across an example I don't understand. Here is the sample code.
using System;
public class Printer
{
public void Print<T>(T argument)
{
Console.WriteLine(argument.ToString());
}
static void Main(string[] arguments)
{
Printer printer = new Printer();
printer.Print<string>("Hello, World");
Console.WriteLine("Done");
Console.ReadKey();
}
}
What is confusing me is the argument to the Print method. I understand using a generic type placeholder when dealing with a collections such as List<T>. However what I don't understand is how <T> comes into play with a method? Is the code just saying that the type of the parameter passed into the Print() method is just not known at design time and could be anything? Could someone help me decipher this? Thank you.
By declaring your method with a generic type, you make your method more flexible as it can then work with variables of any type you choose, including primitive types (unless you specify where T : class of course).
Another very common example that much better illustrates one use of a generic method is a Swap<T>(T, T) method:
/*
* The ref keywords mean "pass by reference" i.e. modify the variables as they
* were passed into the method.
*
* The <T> in the signature tells the compiler that T is a generic type, in case
* the class itself doesn't already declare T a generic type.
*/
public void Swap<T>(ref T x, ref T y)
{
// Tells the compiler that temp should be of the same type as x and y,
// regardless of what type T may be
T temp = x;
x = y;
y = temp;
}
int x = 3, y = 6;
Swap<int>(ref x, ref y);
Console.WriteLine(x + " " + y);
char a = 'a', b = 'b';
Swap<char>(ref a, ref b);
Console.WriteLine(a + " " + b);
Exactly what you wrote. Generic parameters are also possible at method level. They act exactly like on class level, just the scope of the type parameter is limited to the method.
Is the code just saying that the type of the parameter passed into the Print() method is just not known at design time and could be anything?
That's precisely what it's saying. Now, whenever the compiler finds a reference to a T it will automagically substitute the type that was specified in the instance or method call (if the method is generic). A prime example of that type of method is a pattern I've used (and seen used) many times. It's basically a safe cast from one type to another. The type you want to coerce to is specified as the generic parameter. Example:
var something = SafeCast<int>("123.434"); // something == 123
var somethingElse = SafeCast<int>(23.45f); // somethingElse == 23
var somethingNull = SafeCast<int>(null); // this shouldn't throw but return a null
As the compiler does not know what T is, and T isnt defined at class-level, then the compiler needs to know what to cast the parameters to, thats where the argument comes into play ;)
This feels like a too easy question to be found with google, I think/hope I've got stuck in the details when trying to implement my own version of it. What I'm trying to do is to sort a list of MyClass objects depending on my Datatype object different search functions should be used.
I've had something like this in mind for the class Datatype:
class Datatype {
public delegate int CMPFN(object x, object y);
private CMPFN compareFunction;
(...)
private XsdDatatype((...), CMPFN compareFunction) {
(...)
this.compareFunction = compareFunction;
}
public CMPFN GetCompareFunction() {
return this.compareFunction;
}
static private int SortStrings(object a, object b) {
return ((MyClass)a).GetValue().CompareTo(((MyClass)b).GetValue());
}
}
And later on I'm trying to sort a MyClass list something like this:
List<MyClass> elements = GetElements();
Datatype datatype = new Datatype((...), Datatype.SortStrings);
elements.Sort(datatype.GetCompareFunction()); // <-- Compile error!
I'm not overly excited about the cast in Datatype.SortStrings but it feels like this could work(?). The compiler however disagrees and gets me this error on the last line above and I'm a bit unsure exactly why CMPFN can't be converted/casted(?) to IComparer.
Cannot convert type 'proj.Datatype.CMPFN' to 'System.Collections.Generic.IComparer<proj.MyClass>'
Delegates aren't duck-typed like that. You can create an Comparison<MyClass> from a CMPFN but you can't use a plain reference conversion - either implicit or explicit.
Three options:
Create the comparer like this:
elements.Sort(new Comparison<MyClass>(datatype.GetCompareFunction()));
Use a lambda expression to create a Comparison<T> and use that instead:
elements.Sort((x, y) => datatype.GetCompareFunction()(x, y));
Write an implementation of IComparer<MyClass> which performs the comparison based on a CMPFN
Note that the second approach will call GetCompareFunction once per comparison.
A much better solution would be to get rid of CMPFN entirely - why not just use (or implement) IComparer<MyClass> to start with? Note that that would remove the casts as well. (If you're happy using delegates instead of interfaces, you could express the comparison as a Comparison<MyClass> instead.)
Note that as of .NET 4.5, you can use Comparer.Create to create a Comparer<T> from a Comparison<T> delegate.
I'm not sure why your current API is in terms of object, but you should be aware that in C# 3 and earlier (or C# 4 targeting .NET 3.5 and earlier) you wouldn't be able to convert an IComparer<object> into an IComparer<MyClass> (via a reference conversion, anyway). As of C# 4 you can, due to generic contravariance.
There are a number of overloads of List<T>.Sort, but there are none which take a delegate with the parameters you have defined (two objects).
However, there is an overload that takes a Comparison<T> delegate, which you can work with your code with a few minor modifications. Basically, you just replace your CMPFN delegate with Comparison<MyClass> - as an added bonus, you get strong-typing in your SortStrings function, too:
static private int SortStrings(MyClass a, MyClass b) {
return a.GetValue().CompareTo(b.GetValue());
}
public Comparison<MyClass> GetCompareFunction() {
return SortStrings; // or whatever
}
...
elements.Sort(datatype.GetCompareFunction());
Try something like this
class AttributeSort : IComparer<AttributeClass >
{
#region IComparer Members
public int Compare(AttributeClass x, AttributeClass y)
{
if (x == null || y == null)
throw new ArgumentException("At least one argument is null");
if (x.attributeNo == y.attributeNo) return 0;
if (x.attributeNo < y.attributeNo) return -1;
return 1;
}
#endregion
}
You can call it then like this
List<AttributeClass> listWithObj ....
listWithObj.Sort(new AttributeSort());
Should work like you want. You can create a type-safe comparer class as well.