I have several places where i have Action<Int32>, Action<Boolean>, Action<SomeClassName> being used, but when it comes to passing the action as an argument in a class method, i cannot cast Action<Int32> or Action<Boolean> to Action<Object>.
Why can a cast not be done with a simple type cast? Is this cast possible at all? And lastly, how would i go about this cast if it is possible.
Because it would break type safety.
When you declare Action<Int32>, you say "this is a delegate that requires one Int32 parameter".
If this could be directly cast to Action<object>, then you are now able to call the action with something that is definitely not Int32, for instance a DateTime. In this case, C# prevents you from shooting yourself in the foot.
You can't make a direct cast via covariance (or is it contravariance?) because an Action<int> is fundamentally not an Action<object> - the latter can be passed any object, whereas the former can only be passed an int.
You can work around this by wrapping your action, something like:
Action<int> aInt = ...;
Action<object> aObj = o => aInt((int)o);
This again shows you why the cast might not be a good idea - if you pass aObj anything except an int, you'll get a cast exception.
Conversely, you can in theory just cast an Action<object> to an Action<int>, because if you can pass it any object, you can certainly pass it an int. However, in practice this only works for reference types, not value types - so you could do it with string, but not with int.
Action labors under the restriction that its input is an Int32. This means that the action you use can make assumptions about the input being an int. Eg you can do math with another int n => Console.WriteLine(n + 4). So that action, or function, fits nicely in that box. If you change the box, the assumptions made earlier still have to hold. You basically have a reverse relationship, or contravariance, to the "regular" casting scenario, eg: object a = (object) 2;.
Just remember that anything that fits in the Action box has to make no assumptions about the behaviour of its input. The function n => Console.WriteLine(n) fits snugly inside, because all objects can be printed. Not all objects can act like ints.
Related
I'm currently implementing a simple version of algorithmic differentiation with operator overloading in C#. I'm trying to figure out how to design generic math functions that works for with ordinary doubles and my own class "ADouble" that works like a double, but overloads arithmetic operators like +,*,- and so forth.
For instance, i would like to create a function like
Public T MathFunction<T>(T x) where T : "is either double or Adouble"
{
if (x > 0)
return new T(1.0)
else
// something
}
that works for both doubles and ADoubles. In this case it's necessary for me to "new up" a specific value (here 1.0). In other cases i might have to do something like
Public T MathFunction<T>(T x) where T : "is either double or Adouble"
{
T temporaryVar = 2*x;
// .. More calculations
return "some T";
}
I have implemented the necessary interfaces to do a comparison like the above, but i cannot get the rest to work.
I can instantiate my ADouble class with a double by, say
Adouble myADouble = new ADouble(12.3);
but doubles does not have a constructor that works that way, obviously. I've tried different things. First of all i thought of something like
if (typeof(T) == typeof(ADouble)
return new ADouble(1.0)
but this does not work, since the function cannot cast ADouble to a T explicitly (which i understand).
Does anyone have a suggestion on how i could go about implementing generic calculation functions that works with my ADouble class and doubles? Or is the only option to make multiple methods with different signatures? Different suggestions for designs is also greatly appreciated.
Or is the only option to make multiple methods with different signatures?
Called "method overloading".
Yes. This is the correct way to express your "type A or type B" constraint, especially since even if you could successfully express that as a generic constraint, you are still left with the challenge of calling the appropriate constructor.
There is no mechanism in C# generics by which the statement return new T(1.0); could be made to compile successfully. Doing so would require some syntax that additionally constrains the types to those with a constructor that has a single parameter of type double, and there is no such feature in C#.
this does not work, since the function cannot cast ADouble to a T explicitly
Actually, it's that it can't cast implicitly. But, close enough. :)
That would be the next hurdle you'd have to clear. Ironically, this is the simplest. The issue there is that, as you wrote the expression, the compiler knows enough about what's going on to know it can't guarantee the cast will succeed. But if you cast the value to object first, you can then cast it to T without the compiler complaining.
Not that I'm suggesting doing that, mind you. The real issue here is that you are trying to use generic syntax for something that really isn't generic. Generic code is for where you can use any type, or at least a broadly constrained type. If you have specific types in mind, and especially if the implementation is different for each specific type, then you should not be using generics.
In that situation, method overloading is much more appropriate.
Aside: assuming your ADouble type is literally equivalent to double, and you can implement a conversion without any loss of data, you should consider writing an implicit conversion, to help make the types interchangeable. That would look something like this:
public static implicit operator ADouble(double value)
{
return new ADouble(value);
}
Then you can initialize ADouble values with simple assignments, like:
ADouble adouble = 1.0;
Quick question.
In the second example on this documentation page (the second code block, featuring a method called CompareDinosByLength), the Sort method is called as such:
dinosaurs.Sort(CompareDinosByLength);
Why is it that the Sort method didn't need an explicitly declared delegate, as I would have thought by reading the Delegate documentation? Before I found that example, I was attempting to do it like so:
delegate int CompareDinosDel(string first, string second);
CompareDinosDel newDel = CompareDinosByLength;
dinosaurs.Sort(newDel);
But I kept getting errors related to the delegate / delegate method not being proper Comparers.
Shouldn't both work?
Why is it that the Sort method didn't need an explicitly declared delegate?
C# permits a method group -- that is, a method which is named without having the (...) argument list to invoke it -- to be used in a context where a delegate is expected. The compiler performs overload resolution on the method group as though the method group had been invoked with arguments of the types of the delegate's formal parameters. This determines which method of the method group should be used to create the delegate.
This overload resolution process can sometimes lead to unusual situations involving method type inference when the method group is undergoing overload resolution to a delegate type which is a formal parameter type of a generic method; Sort, fortunately is not a generic method, so these oddities do not come into play.
This feature was added to C# 2.0; before that a method group had to be converted to a delegate via
new MyDelegate(MyMethod)
I keep getting errors related to the delegate / delegate method not being proper Comparers. Shouldn't both work?
Unfortunately, no. C# does not have structural identity on delegate types. That is:
delegate void Foo();
delegate void Bar();
...
Foo foo = ()=>{};
Bar bar = foo; // ERROR!
Even though Foo and Bar are structurally identical, the compiler disallows the conversion. You can however use the previous trick:
Bar bar = foo.Invoke;
This is equivalent to
Bar bar = new Bar(foo.Invoke);
However the new bar has as its action to invoke foo; it goes through a level of indirection.
This feature does make some sense.
Reason one:
You don't expect structural identity to work in other places:
struct Point { int x; int y; ... }
struct Pair { int key; int value; ... }
....
Point point = whatever;
Pair pair = point; // ERROR
Reason two:
You might want to say:
delegate int PureMethod(int);
And have a convention that PureMethod delegates are "pure" -- that is, the methods they represent do not throw, always return, return a value computed only from their argument, and produce no side effects. It should be an error to say
Func<int, int> f = x => { Console.WriteLine(x); return x+1; };
PureMethod p = f;
Because f is not pure.
However in hindsight people do not actually make semantics-laden delegates. It is a pain point that a value of type Predicate<int> cannot be assigned to a variable of type Func<int, bool> and vice versa.
If we had to do it all over again, I suspect that delegates would have structural identity in the CLR.
Finally, I note that VB is much more forgiving about inter-assigning mixed delegate types; it automatically builds an adapter delegate if it needs to. This can be confusing because sometimes it looks like referential identity is maintained when in fact it is not, but this is in keeping with the VB philosophy of "just make my code work".
dinosaurs.Sort(CompareDinosByLength);
CompareDinosDel newDel = CompareDinosByLength;
dinosaurs.Sort(newDel);
Shouldn't both work?
No, because you are passing two very different things into those two function calls.
The key here is to recognize that, in both cases, what you actually pass into the method is a delegate. In the first case, the compiler is implicitly creating a delegate of the correct type for you, even though you didn't explicitly ask it to. In the second case, you're making your own delegate, but it's the wrong type, so that attempt will fail.
Starting with .NET 2.0, the C# compiler allow you to skip explicitly create delegates in many situations. If you use a method name in a context where a delegate is expected, and the compiler can verify that the method signature and delegate signature match, it will implicitly construct a delegate instance using the method. That is, instead of doing this (the "old" way)
this.SubmitButton.Click += new System.EventHandler(this.SubmitButton_Click);
You can now do this:
this.SubmitButton.Click += this.SubmitButton_Click;
Visual Studio itself will still generate the older syntax, I assume because it still works and because it's not worth the developer's time to go messing around with it for very little benefit. However, most popular code analysis tools will flag the redundant delegate creation if you use it in your own code.
This same technique works anywhere you have a method (technically a "method group", since one method name can refer to more than one overload), and you assign it to a variable of a delegate type. Passing a method as a parameter into another method is the same type of assignment operation: you are "assigning" the actual parameter at the call site to the formal parameter in the method body, so the compiler does the same thing. In other words, the following two method calls do exactly the same thing:
dinosaurs.Sort(CompareDinosByLength);
dinosaurs.Sort(new Comparison<string>(CompareDinosByLength));
Your unsuccessful attempt to make a delegate, on the other hand, did something slightly different:
dinosaurs.Sort(new CompareDinosDel(CompareDinosByLength));
This time, you told the compiler exactly what kind of delegate you wanted, but that's not the kind of delegate that the method expected. In general, the compiler isn't going to try to second guess what you told it do to; if you ask it to do something that looks "fishy", it will produce an error (in this case, a type mismatch error).
This behavior is similar to what would happen if you tried to do this:
public class A
{
public int x;
}
public class B
{
public int x;
}
public void Foo(A a) { }
public void Bar()
{
B b = new B();
this.Foo(b);
}
In this case, A and B are two distinct types, even though their "type signature" is exactly the same. Any line of code that works on an A will also work equally well on a B, but yet, we cannot use them interchangeably. Delegates are types like any other types, and C#'s type safety rules require that we use the correct delegate types where we need them, and can't get away with just using a close enough type.
The reason this is a good thing is because a delegate type may have a lot more meaning that just it's technical components would imply. Like any other data type, when we create delegates for our applications, we usually apply some kind of semantic meaning to those types. We expect, for example, that if we have a ThreadStart delegate, that it's going to be associated with a method that runs when a new thread starts. the delegate's signature is about as simple as you get (no parameters, no return value) but the implication behind the delegate is very important.
Because of that, we generally want the compiler to tell us if we try to use the wrong delegate type in the wrong place. More often than not, that's probably a sign that we are about to do something that may compile, and even run, but is likely to do the wrong thing. That's never something you want from your program.
While all that is true, it's also true that often times you really don't want to assign any semantic meaning to your delegates, or else, the meaning is assigned by some other part of your application. Sometimes you really do just want to pass around an arbitrary piece of code that has to run later. This is very common with functional-style programs or asynchronous programs, where you get things like continuations, callbacks, or user-supplied predicates (look at the various LINQ methods, for example). .NET 3.5 and onward supply a very useful set of completely generic delegates, in the Action and Func family, for this purpose.
Consider the following code:
public class Foo
{
public int Bar { get; set; }
}
public class SomeOtherFoo
{
public int Bar { get; set; }
}
Should I be able to say:
Foo foo = new SomeOtherFoo();
That won't work in C# either. When you have two different types that have the same body/implementation, they are still different types. Two classes with the same properties are still different classes. Two different delegates with the same signature are still different delegates.
The Sort method has already defined the delegate type, and you need to match it. This is very much like it defining a class that it needs to accept as a parameter; you can't just pass in another type with the same properties and methods.
This is what it means for a language to be statically typed. An alternate type system would be to use "Duck Typing" in which the language doesn't apply the constraint that a variable be of a specific type, but rather that it has a specific set of members. In other words, "If it walks like a duck, and quacks like a duck, pretend it's a duck." That is opposed to the style of typing that says, "It must be a duck, period, even if it knows how to walk and quack."
I'm building a HTTP-API wrapper for .NET, which has a bunch of methods to set data in an object, and then it serializes the data and sends it to my server. There are 6 datatypes allowed:
string
int
long
float
double
DateTime
My data attributes use generics:
SetAttribute<T>(string key, T value)
So there is only one generic method to set data. Since I cannot constrain the data types to the 6 mentioned, I use run-time checks and throw an exception when the wrong data type is used.
Now for my problem: I have two versions of SetAttribute, one that takes a single value (of type T) and one that takes multiple values (of type IEnumerable<T>). The problem is that when a programmer uses this wrapper and does not specify the type parameter, the runtime guesses which method to use, for instance:
SetAttribute("testkey","thing,anotherthing,athirdthing".Split(','))
This defaults to the single value method and T is String[] which of course makes my method cast an exception because String[] is not a valid type. If you specify:
SetAttribute<string>("testkey","thing,anotherThing,aThirdThing".Split(','))
The runtime chooses the correct method (multi-value) and no exception is cast because T is then string.
My question: how can I label my methods so that the type parameter is mandatory and must be explicitly defined? Or do I have to detect this at runtime and redirect to the multi-method myself?
Ok, this was originally a comment above since it doesn't necessarily answer your original question but suggests an alternate approach;
I would say using a public generic SetAttribute in this case isn't necessarily a good idea.
Since the types are so constrained, you should probably just write the overloads and move the errors from runtime to compile time. It would also allow you to take IEnumerable<string> etc. with another 6 overloads and eliminate the problem you're having entirely.
You can always implement SetAttribute with a private generic and just call that from each overload, that will remove some duplication.
It will also more or less eliminate the need for runtime checks, since the types are already constrained by the compiler.
Given a parameter type, the compiler finds a best match from your overloads. If you cast your string[] to an IEnumerable<string> you will probably find it works as expected because the best match is a method that has exactly those parameters. But you have no method that takes a string[], so given one as a parameter, the compiler makes the best guess it can.
I would have two separately named methods rather than overloads otherwise it is too easy to run into this problem. Or have 6 separate overloads, as #Joachim suggests.
I would suggest a better solution would be to test whether the value passed in is IEnumerable after it fails everything else and treat it as such if it is. (I imagine that you're handling IEnumerable as a seventh case already).
One solution would be to break your original method into 6 non-generic overloads, and add another generic overload for collections:
void SetAttribute(string key, int value);
void SetAttribute(string key, string value);
// etc
// abd this takes care of collections:
void SetAttribute<T>(string key, IEnumerable<T> value);
I'm not sure if this is doable, but I will just give a shot.
I am calling Assert.AreEqual() method.
For the parameters, I'm passing...
an enum value which has Int32 as the underlying type because I didn't specify the base type
an int (Int32) value
Assert fails because it sees that the enum is not int (which is definitely correct).
However, is there a way to make this Assert pass when the enum has the correct int value as the 2nd parameter?
I can cast the enum to int and have it a quick fix, but it's really ugly.
I was expecting some kind of overriding a method that Assert uses to compare 2 different objects and implicitly make that enum type look like an int. However, I wasn't successful at finding any hint/answer around that so far.
Someone suggested to create a type converter and use the TypeConverterAttribute to get around. If this works for sure and is the only way to do it, I would; however, it does seem a lot of unnecessary work.
By calling Assert.AreEqual(enum, int), you are calling the Assert.AreEqual(object, object) method, as there is no overload that has an enum and an int as parameters.
I do not think that casting the enum to an int is ugly - in fact I think it is perfectly acceptable and a very common technique. If you were doing a normal equality comparison (ie. 1 == MyEnum.Value), you would get a compiler error as there is no implicit conversion, only an explicit one which requires a cast to work.
A type converter may work, but you need to ask yourself if doing that will actually give you any real benefit for the amount of effort involved. Personally, I would just leave the cast to an int.
If you are asserting something like the return value of a method call, why not just assert based on what value you expect?
MyEnum actual = SomeMethod();
Assert.AreEqual(MyEnum.Value, actual);
This does not require the cast as the two types are the same, and you are asserting the expected value.
I was expecting some kind of overriding a method that Assert uses to compare 2 different objects and implicitly make that enum type look like an int.
That won't work, since Assert.AreEqual is a static method, and you cannot override static methods, nor can you add overloads for static methods through extension methods.
Anyway, even if you could, you would violate the contract for Assert.AreEqual. You want to have Assert.AreEqual(myEnum.One, 1) yield true, although myEnum.One.Equals(1) as well as 1.Equals(myEnum.One) return false. That's inconsistent.
Casting to int is not ugly, it's the correct solution to your problem. After all, you want to check if the numerical value of the enum matches some integer. If that's what you want to check, write it down like this.
So I understand what boxing and unboxing is. When's it come up in real-world code, or in what examples is it an issue? I can't imagine doing something like this example:
int i = 123;
object o = i; // Boxing
int j = (int)o; // Unboxing
...but that's almost certainly extremely oversimplified and I might have even done boxing/unboxing without knowing it before.
It's much less of an issue now than it was prior to generics. Now, for example, we can use:
List<int> x = new List<int>();
x.Add(10);
int y = x[0];
No boxing or unboxing required at all.
Previously, we'd have had:
ArrayList x = new ArrayList();
x.Add(10); // Boxing
int y = (int) x[0]; // Unboxing
That was my most common experience of boxing and unboxing, at least.
Without generics getting involved, I think I'd probably say that reflection is the most common cause of boxing in the projects I've worked on. The reflection APIs always use "object" for things like the return value for a method - because they have no other way of knowing what to use.
Another cause which could catch you out if you're not aware of it is if you use a value type which implements an interface, and pass that value to another method which has the interface type as its parameter. Again, generics make this less of a problem, but it can be a nasty surprise if you're not aware of it.
Boxing (in my experience) usually occurs in these cases:
A value type is passed to a method that accepts an argument of type Object.
A value type is added to a non-generic collection (like an ArrayList).
Other times you can see boxing and unboxing is when you use reflection as the .NET framework's reflection API makes heavy use of Object.
Boxing/unboxing occurs when a value type (like a struct, int, long) is passed somewhere that accepts a reference type - such as object.
This occurs when you explicitly create a method that takes parameters of type object that will be passed value types. It also comes up when you use the older non-generic collections to store value types (typically primitives).
You will also see boxing occuring when you use String.Format() and pass primitives to it. This is because String.Format() accepts a params object[] - which results in boxing of the additional parameters in the call.
Using reflection to invoke methods can also result in boxing/unboxing, because the reflection APIs have no choice but to return object since the real type is not known at compile time (and the Reflection APIs cannot be generic).
The newer generic collections do not result in boxing/unboxing, and so are preferable to the older collections for this reason (eg ArrayList, Hashtable, etc). Not to mention they are typesafe.
You can avoid boxing concerns by changing methods that accept objects to be generic. For example:
public void string Decorate( object a ) // passing a value type results in boxing
{
return a.ToString() + " Some other value";
}
vs:
public void string Decorate<T>( T a )
{
return a.ToString() + " some other value";
}
Here is a really nasty one :)
SqlCommand cmd = <a command that returns a scalar value stored as int>;
// This code works very well.
int result = (int)cmd.ExecuteScalar();
// This code will throw an exception.
uint result = (uint)cmd.ExecuteScalar();
The second execute fails because it tries to unbox an Int32 into an UInt32 which is not possible. So you have to unbox first and than cast.
uint result = (uint)(int)cmd.ExecuteScalar();
Boxing and unboxing is really moving from value type to reference type. So, think of it as moving from the stack to the heap and back again.
There certainly are cases where this is relevant. The inclusion of generics in the 2.0 framework cut a lot of common boxing cases out of practice.
It happens all the time when people do not know what the implications are, simply don't care or sometimes one cannot help but accept boxing as the lesser evel.
Strongly typed datarows will box/unbox pretty much all the time when you access a value-type property.
Also, using a value type as an interface reference will box it as well. Or getting a delegate from an instance method of a value type. (The delegate's target is of type Object)
Since the advent of strongly-typed lists and dictionaries using generics with C# 2.0 (Visual Studio 2005), I think the importance of keeping boxing/unboxing in mind have been amazingly minimized. Add to that nullable types (int?, etc.) and using the null coalescing operator (??) and it really shouldn't be much of a concern at all and would likely not see it in any code that's not 1.1 Framework or earlier.
"The type parameter for an ArrayList must be a class, not a primitive type, so Java provides wrapper classes for the primitive types, like "Integer" for int, "Double" for double, etc.
For more explanation:
An array is a numbered sequence of elements, and each element acts like a separate variable."
Java provides a special syntax for "for" loops over the elements of arrays (and other collection types in Java). The simplified syntax is called a "for-each" loop. For example, the following statement prints each String in an array called "words".
for (String word : words) System.out.println(word);
An array has a number of elements that are set when the array object is created and cannot be changed. Java provides the "ArrayList" class for the functionality of a dynamic array, an array that can change in size. ArrayList is an example of a parameterized type, a type that depends on another type." Eck (2019)
References :
Introduction to Programming Using Java, Eck (2019) describes as follows in Chapter 7