When we create a delegate in C#, to point a function with a definite signature (parameter set), it asks us to specify the identifier also for each type.
public delegate void myDelegate(int x, int y);
if I try to write this prototype declaration as:
public delegate void myDelegate(int, int)
it shows a compile time error saying identifier expected.
But according to me, when we are just specifying the prototype for the method, why compiler needs an identifier to distinguish between two methods with different signature:
public delegate void firstDelegate(int);
and
public delegate void secondDelegate(int, int);
are the sufficient and clear declaration to distinguish between them. I think so
I think you people got me??
It can make a difference at the point of invocation. For example:
using System;
class Test
{
delegate void Foo(int x, int y);
static void Main()
{
Foo foo = (x, y) => Console.WriteLine("x={0}, y={1}", x, y);
foo(x: 5, y: 10);
foo(y: 10, x: 5);
}
}
The output is x=5, y=10 for both lines, because the arguments use names rather than positions. Even though C# only gained named arguments in C# 4, VB.NET has had them for much longer.
Now of course it didn't have to be like that. It could have been designed so that delegates didn't have named parameters in the first place - but when everything else you invoke has named parameters, why would you want to make delegates different?
Would you propose the same for interface methods and abstract methods, by the way? Again, there's no direct use of the parameters in the declarations, as they're just signatures.
Note that parameter names help in terms of readability and allow the parameters to be documented more easily too.
Related
I was translating some C++ code to C# and there was a function pointer within a structure definition, say func*
This func* was a pointer to a lot of other function pointers all contained within a C++ header file (This header file won't be translated).
Is there a way to translate this?
Code snippet:
struct CK_FUNCTION_LIST {
int version;
/* Pile all the function pointers into it. */
#include "pkcs11f.h"
};
The class which I wish to translate contained a member of typeCK_FUNC_LIST*.
To demonstrate what you usually do when you want to use the equivalent of function pointers in C#, take a look at this:
struct MyFunctions {
public Func<int,string,bool> ptr1;
public Action<int> ptr2;
}
class Program
{
static void Main(string[] args)
{
MyFunctions sample = new MyFunctions() { ptr1 = TestValues, ptr2 = DoThing };
sample.ptr1(42, "Answer");
sample.ptr2(100);
}
static bool TestValues(int a, string b)
{
Console.WriteLine("{0} {1}", a, b);
return false;
}
static void DoThing(int a)
{
Console.WriteLine("{0}", a);
}
}
The output is:
42 Answer
100
If you are porting the code, you have a couple of options in C#:
1) Use lamdas (e.g. unnamed delegates). If these are 1-off functions (e.g. they are only used once), this will be the best choice.
2) Use named delegates. These will behave very similarly to C++ function pointers. If you are using the same functions in several places, this will be the better choice.
Just for clarification (as Ben Voigt pointed out): these are effectively the same thing as the lamda syntax will create a delegate for you.
The delegate type can be framework-provided (Action, Func, Predicate)
or user-declared, and the delegate can be created inline (lambda,
anonymous delegate) or by naming a method.
The normal way of using function pointers in C# is to declare an Action or Func. These are type safe, so they will only accept methods matching the signature of the type arguments.
Delegates are more generic (Action and Func are just specific named ones) but less clear. Really, we'd need more information to be any more specific.
When calling a method with a ref or out parameter, you have to specify the appropriate keyword when you call the method. I understand that from a style and code quality standpoint (as explained here for example), but I'm curious whether there is also a technical need for the keywords to be specified in the caller.
For example:
static void Main()
{
int y = 0;
Increment(ref y); // Is there any technical reason to include ref here?
}
static void Increment(ref int x)
{
x++;
}
The only technical reason I could think of is overload resolution: you could have
static void Increment(ref int x)
and also
static void Increment(int x)
This is allowed; without ref in the call, the compiler wouldn't be able to tell them apart.
If you're asking whether the language could have been designed so that those aren't needed at the call site, the answer is yes. There is no particular reason they could not have been left out. The compiler has all the information it needs from the metadata, so it could make the proper transformation.
That said, doing so would have made it impossible to have these two overloads:
public void DoSomething(int x);
public void DoSomething(ref int x);
The compiler wouldn't be able to disambiguate that.
Although the ref and out could have been made optional, in which case those overloads would be allowed. And the compiler could either take the default (i.e. the non-ref), or issue an ambiguity error and make you specify which one you really wanted.
All that said, I like having to specify ref and out at the call site. It tells me that the parameter could potentially be modified. Having worked in Pascal for many years, where a var parameter is passed the same way that a value parameter is passed (the syntax at the call site is the same), I much prefer the specificity of C# in that regard.
Another reason to require the modifier is to make changing a parameter to a ref or out a breaking change. If the ref/out could be inferred, then an evil programmer changing a parameter from by-value to by-reference would not be detected by clients compiling against the new signature. If a client called the method
public int Increment(int x)
{
return x + 1;
}
by using
int result = Increment(x);
Suppose an evil developer decided to change the implementation to instead change the value passed by reference and return an error code if, say, the increment resulted in an overflow:
public int Increment(ref int x)
{
x = x + 1;
if(x == int.MinValue) // overflow
return -1;
else
return 0;
}
Then a client building against the signature would not receive a compile error, but it would almost certainly break the calling app.
The compiler needs to know the method parameters it is interpreting when it is building IL.
One reason is having overloads like:
public void (ref int x) {}
public void (int x) {}
Another reason is out will explicitly allow you to use pass-by-value parameter use the interpreted value outside the method. ref will give the pointer to the parameter thereby pointing any new value from the method to the same memory location
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 question already has answers here:
Should you declare methods using overloads or optional parameters in C# 4.0?
(13 answers)
Closed 9 years ago.
which one is better? at a glance optional parameter seems better (less code, less XML documentation, etc), but why do most MSDN library classes use overloading instead of optional parameters?
Is there any special thing you have to take note when you choose to use optional parameter (or overloading)?
One good use case for 'Optional parameters' in conjunction with 'Named Parameters' in C# 4.0 is that it presents us with an elegant alternative to method overloading where you overload method based on the number of parameters.
For example say you want a method foo to be be called/used like so, foo(), foo(1), foo(1,2), foo(1,2, "hello"). With method overloading you would implement the solution like this,
///Base foo method
public void DoFoo(int a, long b, string c)
{
//Do something
}
/// Foo with 2 params only
public void DoFoo(int a, long b)
{
/// ....
DoFoo(a, b, "Hello");
}
public void DoFoo(int a)
{
///....
DoFoo(a, 23, "Hello");
}
.....
With optional parameters in C# 4.0 you would implement the use case like the following,
public void DoFoo(int a = 10, long b = 23, string c = "Hello")
Then you could use the method like so - Note the use of named parameter -
DoFoo(c:"Hello There, John Doe")
This call takes parameter a value as 10 and parameter b as 23.
Another variant of this call - notice you don't need to set the parameter values in the order as they appear in the method signature, the named parameter makes the value explicit.
DoFoo(c:"hello again", a:100)
Another benefit of using named parameter is that it greatly enhances readability and thus code maintenance of optional parameter methods.
Note how one method pretty much makes redundant having to define 3 or more methods in method overloading. This I have found is a good use case for using optional parameter in conjunction with named parameters.
Optional Parameters provide issues when you expose them publicly as API. A rename of a parameter can lead to issues. Changing the default value leads to issues (See e.g. here for some info: Caveats of C# 4.0 optional parameters)
Also, optional params can only be used for compile-time constants. Compare this:
public static void Foo(IEnumerable<string> items = new List<string>()) {}
// Default parameter value for 'items' must be a compile-time constant
to this
public static void Foo() { Foo(new List<string>());}
public static void Foo(IEnumerable<string> items) {}
//all good
Update
Here's some additional reading material when a constructor with default parameters does not play nicely with Reflection.
I believe they serve different purposes. Optional parameters are for when you can use a default value for a parameter, and the underlying code will be the same:
public CreditScore CheckCredit(
bool useHistoricalData = false,
bool useStrongHeuristics = true) {
// ...
}
Method overloads are for when you have mutually-exclusive (subsets of) parameters. That normally means that you need to preprocess some parameters, or that you have different code altogether for the different "versions" of your method (note that even in this case, some parameters can be shared, that's why I mentioned "subsets" above):
public void SendSurvey(IList<Customer> customers, int surveyKey) {
// will loop and call the other one
}
public void SendSurvey(Customer customer, int surveyKey) {
...
}
(I wrote about this some time ago here)
This one almost goes without saying, but:
Not all languages support optional parameters. If you want your libraries to be friendly to those languages, you have to use overloads.
Granted, this isn't even an issue for most shops. But you can bet it's why Microsoft doesn't use optional parameters in the Base Class Library.
Neither is definitively "better" than the other. They both have their place in writing good code. Optional parameters should be used if the parameters can have a default value. Method overloading should be used when the difference in signature goes beyond not defining parameters that could have default values (such as that the behavior differs depending on which parameters are passed, and which are left to the default).
// this is a good candidate for optional parameters
public void DoSomething(int requiredThing, int nextThing = 12, int lastThing = 0)
// this is not, because it should be one or the other, but not both
public void DoSomething(Stream streamData = null, string stringData = null)
// these are good candidates for overloading
public void DoSomething(Stream data)
public void DoSomething(string data)
// these are no longer good candidates for overloading
public void DoSomething(int firstThing)
{
DoSomething(firstThing, 12);
}
public void DoSomething(int firstThing, int nextThing)
{
DoSomething(firstThing, nextThing, 0);
}
public void DoSomething(int firstThing, int nextThing, int lastThing)
{
...
}
Optional parameters has to be last. So you can not add an extra parameter to that method unless its also optional. Ex:
void MyMethod(int value, int otherValue = 0);
If you want to add a new parameter to this method without overloading it has to be optional. Like this
void MyMethod(int value, int otherValue = 0, int newParam = 0);
If it can't be optional, then you have to use overloading and remove the optional value for 'otherValue'. Like this:
void MyMethod(int value, int otherValue = 0);
void MyMethod(int value, int otherValue, int newParam);
I assume that you want to keep the ordering of the parameters the same.
So using optional parameters reduces the number of methods you need to have in your class, but is limited in that they need to be last.
Update
When calling methods with optional parameters, you can used named parameters like this:
void MyMethod(int value, int otherValue = 0, int newValue = 0);
MyMethod(10, newValue: 10); // Here I omitted the otherValue parameter that defaults to 0
So optional parameters gives the caller more possibilities.
One last thing. If you use method overloading with one implementation, like this:
void MyMethod(int value, int otherValue)
{
// Do the work
}
void MyMethod(int value)
{
MyMethod(value, 0); // Do the defaulting by method overloading
}
Then when calling 'MyMethod' like this:
MyMethod(100);
Will result in 2 method calls. But if you use optional parameters there is only one implementation of 'MyMethod' and hence, only one method call.
What about a 3rd option: pass an instance of a class with properties corresponding to various "optional parameters".
This provides the same benefit as named and optional parameters, but I feel that this is often much clearer. It gives you an opportunity to logically group parameters if necessary (i.e. with composition) and encapsulate some basic validation as well.
Also, if you expect clients that consume your methods to do any kind of metaprogramming (such as building linq expressions involving your methods), I think that keeping the method signature simple has its advantages.
A good place to use optional parameter is WCF since it does not support method overloading.
This is not really an answer to the original question, but rather a comment on #NileshGule's answer, but:
a) I don't have enough reputation points to comment
b) Multiple lines of code is quite hard to read in comments
Nilesh Gule wrote:
One benefit of using optional parameters is that you need not have to do a conditional check in your methods like if a string was null or empty if one of the input parameter was a string. As there would be a default value assigned to the optional parameter, the defensive coding will be reduced to a great extent.
This is actually incorrect, you still have to check for nulls:
void DoSomething(string value = "") // Unfortunately string.Empty is not a compile-time constant and cannot be used as default value
{
if(value == null)
throw new ArgumentNullException();
}
DoSomething(); // OK, will use default value of ""
DoSomething(null); // Will throw
If you supply a null string reference, it will not be replaced by the default value. So you still need to check the input parameters for nulls.
To address your first question,
why do most MSDN library classes use
overloading instead of optional
parameters?
It is for backward compatibility.
When you open a C# 2, 3.0 or 3.5 project in VS2010, it is automatically upgraded.
Just imagine the inconvenience it would create if each of the overloads used in the project had to be converted to match the corresponding optional parameter declaration.
Besides, as the saying goes, "why fix what is not broken?". It is not necessary to replace overloads that already work with new implementations.
One benefit of using optional parameters is that you need not have to do a conditional check in your methods like if a string was null or empty if one of the input parameter was a string. As there would be a default value assigned to the optional parameter, the defensive coding will be reduced to a great extent.
Named parameters give the flexibility of passing parameter values in any order.
If you go right now and type string.Format into your IDE, you'll see that there are 4 different overloads: one taking a string and object, another taking a string and two objects, then one taking three objects, and finally one that uses params. According to this answer, this is because params generates 'overhead', and some other languages may not support it.
My question is, why can't a method call like this:
void Foo()
{
Bar(1, 2, 3);
}
void Bar(params int[] args)
{
// use args...
}
Be essentially transformed at compile time to
void Foo()
{
Bar(new[] { 1, 2, 3 });
}
void Bar(int[] args)
{
// use args...
}
? Then it wouldn't create any overhead except for the array creation (which was necessary anyway), and would be fully compatible with other languages.
The number of arguments is already known at compile-time, so what's preventing the C# compiler from doing some kind of string substitution and making the first scenario essentially syntactic sugar for the second? Why did we have to implement hidden language features specifically to support variadic arguments?
The title makes an incorrect assumption.
Both a params and a non-params methods take an array; the difference is the compiler will emit the IL to create an array implicitly when making a params method call. An array is passed to both methods, as a single argument.
This can be seen in this .NET Fiddle (view "Tidy Up -> View IL").
using System;
public class Program
{
public static void Main()
{
var a1 = 1;
var a2 = 2;
var a3 = 3;
with_params(a1,a2,a3);
no_params(new [] {a1,a2,a3});
}
public static void with_params(params int[] x) {}
public static void no_params(int[] x) {}
}
In both cases the IL is identical; a new array is created, it is populated, and the array is supplied to the invoked method.
There is an "exception" to this identical IL generation in that the compiler can move out constant-valued arrays when used in the non-parameter form and use 'dup' initialization, as seen here. However, a new array is supplied as the argument in both cases.