I wonder if I should be using optional parameters in C#. Until now I was always overloading methods. But optional parameters are nice too, cleaner and less code. And I use them in other languages so I'm also used to them in some way. Is there anything that speaks against using them ? Performance is the first key point for me. Would it drop ?
Example code:
class Program
{
// overloading
private static void test1(string text1)
{
Console.WriteLine(text1 + " " + "world");
}
private static void test1(string text1, string text2)
{
Console.WriteLine(text1 + " " + text2);
}
// optional parameters
private static void test2(string text1, string text2 = "world")
{
Console.WriteLine(text1 + " " + text2);
}
static void Main(string[] args)
{
test1("hello");
test1("hello", "guest");
test2("hello"); // transforms to test2("hello", "world"); ?
test2("hello", "guest");
Console.ReadKey();
}
}
I measured the time needed for a few millions overload calls and optional parameter calls.
optional parameters with strings: 18 % slower (2 parameters, release)
optional parameters with ints: <1 % faster (2 parameters, release)
(And maybe compilers optimize or will optimize those optional parameter calls in future ?)
I just did a quick test and the compiler optimizes the code. This basic example Main method.
public static void OptionalParamMethod(bool input, string input2 = null)
{
}
public static void Main(string[] args)
{
OptionalParamMethod(true);
OptionalParamMethod(false, "hello");
}
Compiles to this so the optional params are filled in by the compiler.
public static void Main(string[] args)
{
OptionalParamMethod(true, null);
OptionalParamMethod(false, "hello");
}
As for performance you could argue optional parameters have a slight advantage as there is only a single method call rather than chained method calls like you would normally have for an overloaded method. The code below is compiled output to show what I am talking about. The difference is quite academic though and I doubt you would ever notice in practice.
public static void Main(string[] args)
{
OptionalParamMethod(true, null);
OptionalParamMethod(false, "hello");
OverloadParamMethod(true);
OverloadParamMethod(false, "hello");
}
public static void OptionalParamMethod(bool input, [Optional, DefaultParameterValue(null)] string input2)
{
Console.WriteLine("OptionalParamMethod");
}
public static void OverloadParamMethod(bool input)
{
OverloadParamMethod(input, null);
}
public static void OverloadParamMethod(bool input, string input2)
{
Console.WriteLine("OverloadParamMethod");
}
Neither overloading nor optional parameters will in themselves cause any changes in performance. As David Ewen noted, the C# compiler produces IL that does not know about optional parameters (this is the sources of some versioning bugs that come from optional parameters on types which can be literal).
As for overloading. C# is a (mostly) statically typed language. The compiled code directly references the address of the appropriate method. There is a small performance hit when overloading AT COMPILE time. In C++ in fact, overloading is done by a process called "name mangling" where each overload at compile time is given a unique name.
However there are cases where overloading CAN impact performance. But these are pretty obvious, like during reflection and in dynamic typed code.
It sounds like you are confused about the performance hit of virtual/abstract functions. In order for the .net runtime to resolve the correct function, there is an extra step which looks up the particular type's implementation of that method.
Related
I have been workig on a report on delegates for some time now in addition to working with them for over a year.
Looking up some info on the differences between anonymous methods used in C# 2.0 and lambda expressions in C# i read something about a functionality that 2.0 anonymous methods provide which lambda's dont: they can omit the parameter list.
After doing some research on this i try testing this out on my personal IDE which is running the latest version of C#, finding out that when i try to assign an anonymous method without any parameters to my Delegate type using them i get an error:
Delegate Test.MyHelloDelegate does not take 0 arguments
class TestClass
{
public delegate void MyHelloDelegate (string s);
MyHelloDelegate Hello = delegate () { Console.WriteLine("Hello from delegate"); };
private void CallHello ()
{
Hello("dummy");
}
}
My own assumption would be that it got patched out since people will only use lambda's anyway but i do need some evidence for that since i will be putting it in my report. Would love to know if someone has any idea what is going on with this.
Yes, cause your attached anonymous method doesn't takes an input parameter. Change it to
public delegate void MyHelloDelegate (string s);
MyHelloDelegate Hello = delegate(string s) { Console.WriteLine("Hello from delegate " + s); };
If you don't want pass any parameter then consider using the syntax below
MyHelloDelegate Hello = delegate { Console.WriteLine("Hello from delegate "); };
Consider the following code in a class library:
public class Service
{
public delegate string Formatter(string s1, string s2);
public void Print(Formatter f)
{
Console.WriteLine(f("a", "b"));
}
}
And here's a console application that uses it:
static void Main(string[] args)
{
s = new Service();
s.Print(Concat);
}
static string Concat(string s1, string s2)
{
return string.Format("{0}-{1}", s1, s2);
}
So far it prints "a-b", just as one would expect.
Now, I change the class library as follows:
public class Service
{
public delegate string Formatter(string s1);
public void Print(Formatter f)
{
Console.WriteLine(f("a"));
}
}
I.e. I removed one parameter from the delegate. I compile the class library only and overwrite the dll sitting next to the console app (console app is not recompiled). I'd expect that this is a breaking change in the library and if I execute the app, it finds the mismatch, resulting in some runtime exception.
In contrast, when I run the app there's no exception at all, and I get the stunning output "-a". When I debug, I can see that the Concat method (with 2 parameters) is called, the call stack level below shows Print calling to f("a") (one parameter), no error indication anywhere. Most interestingly, in Concat s1 is null, s2 is "a".
I also played around with different changes to the signature (adding parameters, changing parameter type) mostly with the same result. When I changed the type of s2 from string to int I got an exception, but not when the Concat method was called, but when it tried to call string.Format.
I tried it with .NET target framework 4.5.1 and 3.5, x86 and x64.
Can anyone answer whether this is the expected behaviour or a bug? It seems pretty dangerous to me.
Here's a simpler repro - basically, I'm using the "under the hood" constructor on the delegate type (the one that the IL uses) to pass a method target with the wrong signature, and... it works fine (by which I mean it doesn't throw an exception - it behaves just like your code):
using System;
static class P
{
static void Main()
{
// resolve the (object, IntPtr) ctor
var ctor = typeof(Func<string, string>).GetConstructors()[0];
// resolve the target method
var mHandle = typeof(P).GetMethod(nameof(Concat))
.MethodHandle.GetFunctionPointer();
object target = null; // because: static
// create delegate instance
var del = (Func<string, string>)ctor.Invoke(new object[] { target, mHandle });
var result = del("abc");
Console.WriteLine(result); // "-abc"
}
public static string Concat(string s1, string s2)
{
return string.Format("{0}-{1}", s1, s2);
}
}
This is not really an explanation. But it might be helpful if you want to ask someone more CLR-expert! I would have expected the delegate constructor to have complained loudly about the target being incorrect.
At a guess (pure speculation), it is a case of: if you're passing an IntPtr (native int), then you're entirely on your own - the code does the fastest thing possible. It does seem like a nasty trap for the unwary, though!
As for why s2 has the value and s1 is empty: I guess that is because the stack builds down (not up), hence in a two parameter method, arg1 is the parameter immediately adjacent to the previous position on the stack. When we pass a single value instead of two, we only put one value underneath, so s2 has a value, and s1 is undefined (could be garbage from previous code).
Going from a lambda to an Expression is easy using a method call...
public void GimmeExpression(Expression<Func<T>> expression)
{
((MemberExpression)expression.Body).Member.Name; // "DoStuff"
}
public void SomewhereElse()
{
GimmeExpression(() => thing.DoStuff());
}
But I would like to turn the Func in to an expression, only in rare cases...
public void ContainTheDanger(Func<T> dangerousCall)
{
try
{
dangerousCall();
}
catch (Exception e)
{
// This next line does not work...
Expression<Func<T>> DangerousExpression = dangerousCall;
var nameOfDanger =
((MemberExpression)dangerousCall.Body).Member.Name;
throw new DangerContainer(
"Danger manifested while " + nameOfDanger, e);
}
}
public void SomewhereElse()
{
ContainTheDanger(() => thing.CrossTheStreams());
}
The line that does not work gives me the compile-time error Cannot implicitly convert type 'System.Func<T>' to 'System.Linq.Expressions.Expression<System.Func<T>>'. An explicit cast does not resolve the situation. Is there a facility to do this that I am overlooking?
Ooh, it's not easy at all. Func<T> represents a generic delegate and not an expression. If there's any way you could do so (due to optimizations and other things done by the compiler, some data might be thrown away, so it might be impossible to get the original expression back), it'd be disassembling the IL on the fly and inferring the expression (which is by no means easy). Treating lambda expressions as data (Expression<Func<T>>) is a magic done by the compiler (basically the compiler builds an expression tree in code instead of compiling it to IL).
Related fact
This is why languages that push lambdas to the extreme (like Lisp) are often easier to implement as interpreters. In those languages, code and data are essentially the same thing (even at run time), but our chip cannot understand that form of code, so we have to emulate such a machine by building an interpreter on top of it that understands it (the choice made by Lisp like languages) or sacrificing the power (code will no longer be exactly equal to data) to some extent (the choice made by C#). In C#, the compiler gives the illusion of treating code as data by allowing lambdas to be interpreted as code (Func<T>) and data (Expression<Func<T>>) at compile time.
private static Expression<Func<T, bool>> FuncToExpression<T>(Func<T, bool> f)
{
return x => f(x);
}
What you probably should do, is turn the method around. Take in an Expression>, and compile and run. If it fails, you already have the Expression to look into.
public void ContainTheDanger(Expression<Func<T>> dangerousCall)
{
try
{
dangerousCall().Compile().Invoke();;
}
catch (Exception e)
{
// This next line does not work...
var nameOfDanger =
((MemberExpression)dangerousCall.Body).Member.Name;
throw new DangerContainer(
"Danger manifested while " + nameOfDanger, e);
}
}
public void SomewhereElse()
{
ContainTheDanger(() => thing.CrossTheStreams());
}
Obviously you need to consider the performance implications of this, and determine if it is something that you really need to do.
If you sometimes need an expression and sometimes need a delegate, you have 2 options:
have different methods (1 for each)
always accept the Expression<...> version, and just .Compile().Invoke(...) it if you want a delegate. Obviously this has cost.
NJection.LambdaConverter is a library that converts a delegate to an expression
public class Program
{
private static void Main(string[] args) {
var lambda = Lambda.TransformMethodTo<Func<string, int>>()
.From(() => Parse)
.ToLambda();
}
public static int Parse(string value) {
return int.Parse(value)
}
}
You can go the other way via the .Compile() method however - not sure if this is useful for you:
public void ContainTheDanger<T>(Expression<Func<T>> dangerousCall)
{
try
{
var expr = dangerousCall.Compile();
expr.Invoke();
}
catch (Exception e)
{
Expression<Func<T>> DangerousExpression = dangerousCall;
var nameOfDanger = ((MethodCallExpression)dangerousCall.Body).Method.Name;
throw new DangerContainer("Danger manifested while " + nameOfDanger, e);
}
}
public void SomewhereElse()
{
var thing = new Thing();
ContainTheDanger(() => thing.CrossTheStreams());
}
Expression<Func<T>> ToExpression<T>(Func<T> call)
{
MethodCallExpression methodCall = call.Target == null
? Expression.Call(call.Method)
: Expression.Call(Expression.Constant(call.Target), call.Method);
return Expression.Lambda<Func<T>>(methodCall);
}
JB Evain from the Cecil Mono team is doing some progress to enable this
http://evain.net/blog/articles/2009/04/22/converting-delegates-to-expression-trees
Change
// This next line does not work...
Expression<Func<T>> DangerousExpression = dangerousCall;
To
// This next line works!
Expression<Func<T>> DangerousExpression = () => dangerousCall();
I am looking into C# logging and I do not want my log messages to spend any time processing if the message is below the logging threshold. The best I can see log4net does is a threshold check AFTER evaluating the log parameters.
Example:
_logger.Debug( "My complicated log message " + thisFunctionTakesALongTime() + " will take a long time" )
Even if the threshold is above Debug, thisFunctionTakesALongTime will still be evaluated.
In log4net you are supposed to use _logger.isDebugEnabled so you end up with
if( _logger.isDebugEnabled )
_logger.Debug( "Much faster" )
I want to know if there is a better solution for .net logging that does not involve a check each time I want to log.
In C++ I am allowed to do
LOG_DEBUG( "My complicated log message " + thisFunctionTakesALongTime() + " will take no time" )
since my LOG_DEBUG macro does the log level check itself. This frees me to have a 1 line log message throughout my app which I greatly prefer. Anyone know of a way to replicate this behavior in C#?
If you can target .NET 3.5 (C# 3.0) you can use extension methods to wrap the if statements.
so you can do the equivalent "macro":
logger.Log_Debug("Much faster");
logger.Log_Debug(() => { "My complicated log message " + thisFunctionTakesALongTime() + " will take no time" });
by wrapping the check in this method:
public class Log4NetExtensionMethods {
// simple string wrapper
public void Log_Debug(this log4net.ILog logger, string logMessage) {
if(logger.isDebugEnabled) {
logger.Debug(logMessage);
}
}
// this takes a delegate so you can delay execution
// of a function call until you've determined it's necessary
public void Log_Debug(this log4net.ILog logger, Func<string> logMessageDelegate) {
if(logger.isDebugEnabled) {
logger.Debug(logMessageDelegate());
}
}
}
17.4.2 The Conditional attribute
The attribute Conditional enables the definition of conditional methods. The Conditional attribute indicates a condition by testing a conditional compilation symbol. Calls to a conditional method are either included or omitted depending on whether this symbol is defined at the point of the call. If the symbol is defined, the call is included; otherwise, the call (including evaluation of the parameters of the call) is omitted.
[ Conditional("DEBUG") ]
public static void LogLine(string msg,string detail)
{
Console.WriteLine("Log: {0} = {1}",msg,detail);
}
public static void Main(string[] args)
{
int Total = 0;
for(int Lp = 1; Lp < 10; Lp++)
{
LogLine("Total",Total.ToString());
Total = Total + Lp;
}
}
The problem here is that all method parameters must be evaluated before the method is invoked. There is no way around this, given the syntax you are using. Since C# does not have a real preprocessor or macros, you can't do anything like "LOG_DEBUG". The best you could do is use if (logger.isDebugEnable) as suggested.
The only thing I can think of is maybe using something like a lambda expression to delay evaluation. But I would warn you that this will almost certainly have more of a performance hit in the end.
internal class Sample
{
private static void Main(string[] args)
{
DelayedEvaluationLogger.Debug(logger, () => "This is " + Expensive() + " to log.");
}
private static string Expensive()
{
// ...
}
}
internal static class DelayedEvaluationLogger
{
public static void Debug(ILog logger, Func<string> logString)
{
if (logger.isDebugEnabled)
{
logger.Debug(logString());
}
}
}
Without a preprocessor you're SOL. Of course there's nothing preventing you from using one before feeding your code to the C# compiler.
Is there any way in C# to pass a random method as a parameter?
To explain my question:
I want to write a simple Logger-Tool that reports the entering and leaving of a method with the passed arguments an the class and method name:
The log file I'm aiming at:
ENTERING: ClassOfDoom::MethodOfDoom( arg1={1} [int], arg2={true} [bool] )
LEAVING: ClassOfDoom::MethodOfDoom RETURNING 1 [int]
The code I have in mind:
class ClassOfDoom {
// Remeber: MethodOfDoom is a _random_ method with _random_ arguments
public int MethodOfDoom(int arg1, bool arg2) {
Log.Entering(this, this.MethodOfDoom, arg1, arg2);
...
return Log.Returing(this, this.MethodOfDoom, 1);
}
}
Is there a way to achieve this? Or isn't C# as flexible as that?
Thanks in advance!
You can make your logging function take a MethodBase argument and use MethodBase.GetCurrentMethod to pass the current method info as an argument.
Then, in the logger, you could check its properties Name and DeclaringType to get the method information. Also, passing parameters is easy by declaring a params object[] args parameter in the logging function:
public static void Entering(object obj, MethodBase methodInfo,
params object[] args) {
Console.WriteLine("ENTERING {0}:{1}", methodInfo.DeclaringType.Name,
methodInfo.Name);
...
}
I'm not sure I entirely understand your question, but if you are trying to make a call to Log.Entering and Log.Returning inside an arbitrary (random) method and using the method's actual parameters, you should check out PostSharp. It will allow you to inject code in a method body and then do some work based on the reflected method information you get from the .NET framework (and the actual parameters passed to the method at runtime).
You could do it with Expression easily enough - it would look something like:
Log.Capture(() => this.MethodOfDoom(arg1, arg2));
Here's an example; I've been a bit lazy using Compile().DynamicInvoke() to read the arg-values - for real code I'd try to read it more directly:
using System;
using System.Diagnostics;
using System.Linq.Expressions;
class Program
{
DateTime MethodOfDoom(string s, int i)
{
return DateTime.Today;
}
public void RunTest()
{
int i =123;
Log.Capture(() => this.MethodOfDoom("abc", i));
}
static void Main()
{
new Program().RunTest();
}
}
static class Log
{
public static T Capture<T>(Expression<Func<T>> method)
{
MethodCallExpression mce = method.Body as MethodCallExpression;
if (mce == null) throw new InvalidOperationException(
"Method-call expected");
string name = mce.Method.Name;
try
{
int i = 0;
foreach(var param in mce.Method.GetParameters())
{
object argValue = Expression.Lambda(mce.Arguments[i++])
.Compile().DynamicInvoke();
Trace.WriteLine(param.Name + "=" + argValue, name);
}
Trace.WriteLine("ENTERING", name);
T result = method.Compile().Invoke();
Trace.WriteLine("EXITING: " + result, name);
return result;
}
catch (Exception ex)
{
Trace.WriteLine("EXCEPTION: " + ex, name);
throw;
}
}
}
If widely used in your code, this scenario is best implemented using Aspect Oriented Programming (AOP) techniques. There are different frameworks that can be used (such as Spring.NET AOP), which you can use in your .NET application. Here is a reference article that might help you get started:
http://www.developer.com/lang/article.php/10924_3795031_2
The referenced article gives you the logging enter/exit scenario as an example.
I have used PostSharp to do this very thing before.