When i get exception, it quite hard read error stack if I have lamda functions.
For example for this code:
public void Test()
{
Func<AnotherClass, bool> myLambda = (AnotherClass p) =>
{
if (p != null)
{
throw new Exception("Exception in method");
}
return true;
};
AnotherClass ac = new AnotherClass();
var r = myLambda(ac);
}
public class AnotherClass
{
}
I will get stack error like:
"CSharpTests.exe Error: 0 : System.Exception: Exception in method
at CSharpTests.MarketingEntityManager.<>c.<Test>b__0_0(AnotherClass p)
at CSharpTests.MarketingEntityManager.Test()
at CSharpTests.DisplayClassTest.Test()"
It was asked many times, what is <>c.b__0_0
But additionally interesting, may be why myLabda name I used in my code, was not used for generate name, and b__0_0 was generated.
and where is DisplayName text?
Your anonymous method isn't named myLambda. A delegate to the anonymous method is assigned to the myLambda local variable. In truth, your anonymous method has a "secret" name, given to it by the compiler, and it is <Test>b__0_0 (and it is then "hidden" in a nested class named <>c), but this name can change between compilations based on the number of other anonymous methods in the same class.
To give a (degenerate) example (that is very common in Javascript), this is legal:
((Func<AnotherClass, bool>)((AnotherClass p) =>
{
if (p != null)
{
throw new Exception("Exception in method");
}
return true;
}))(new AnotherClass());
Here we don't assign the delegate of the method to any variable, but we use it immediately to invoke the class. The number of brackets is terrible :-)
Another classical example:
var coll = new int[5];
var enu = coll.Select(x => x + 1).ToArray();
Here x => x + 1 is an anonymous method (of which a delegate is created by the .NET and passed to Enumerable.Select)... There is no name anywhere.
myLamda is just the name of the delegate that references your method. It´s not the name of that method. The latter is generated from the compiler, you can´t change it.
To clearify this a little imagine you didn´t have an anonymous method at all and would reference named method with your delegate:
myLambda = MyMethod;
Now it´s pretty clear that the stacktrace would contain MyMethod, not myLambda, wouldn´t it?
Related
For performance reasons, I'm trying to reduce the overhead of having a new instance of a reference type created every time a particular method is called.
As a basic example:
public int AccumulativeCount(Expression<Func<int>> exp)
{
// usually do something useful with "exp". Instead put a
// breakpoint and get the memory reference of exp via "&exp"
return 1;
}
When it is called elsewhere in the code, the reference of exp in the AccumulativeCount method is different:
AccumulativeCount(() => 7);
Is there a way to make the parameter from the calling code static inline? In the example above the parameter "() => 7" is obviously never going to change, so there is no compelling reason why it should be recreated every time.
I'm aware that I could change the calling code to be:
public static Expression<Func<int>> MyStaticCountExp = () => 7;
// ... later in the code
AccumulativeCount(MyStaticCountExp);
The reason why I'm against the above is the expression only makes sense in the context that it is a parameter for. Also the code is not as clean as it could be. Is there something like:
AccumulativeCount(static () => 7); // does not compile
I don't know exactly your usecase, but maybe the Lazy<T> class will help.
public static readonly Lazy<int> Something = new Lazy<int>(() => AccumulativeCount(() => 7));
public static int AccumulativeCount(Expression<Func<int>> exp) {
// usually do something useful with "exp". Instead put a
// breakpoint and get the memory reference of exp via "&exp"
return 1;
}
public static void DoSomething() {
// the value was not available, so the AccumulativeCount(...) will be called
var a = Something.Value;
// the value is already created, no more call of AccumulativeCount(...) is needed
var b = Something.Value;
var c = Something.Value;
var d = Something.Value;
}
I was reading about Web API 2 and Entity Framework where I bumped across this line:
this.Database.Log = s => System.Diagnostics.Debug.WriteLine(s);
I looked up the => operator and found that it has something to do with lambdas, although I'm still not sure exactly how it fits in or what's going on here. Can anybody help me out? What's going on in this line?
this.Database.Log = s => System.Diagnostics.Debug.WriteLine(s);
Basically means:
this.Database.Log = blah;
void blah(string s)
{
System.Diagnostics.Debug.WriteLine(s);
}
Database.Log is of the type Action<T>, which is a delegate type
See the property on MSDN
See Action<T> on MSDN
See delegates on MSDN
See lamdas on MSDN
So when this.Database wants to log stuff, it'll call it's "Log" property which is an Action<string>. Since it's an Action<string> (and more importantly, Action<T> is a delegate type), you can assign either a method which returns no value and has a single parameter (which is a string) or a lamda with a single parameter (also, string) (and no return value).
The Database.Log property is of type Action<string>. That means it's a delegate that takes a string and has no return value (i.e. its return type is void). So this line assigns the to the Log property an anonymous function which accepts a string value and writes it to the debugger window.
Because you're assigning the lambda expression to a property with a known delegate type, the compiler can infer the type of the argument (s) and return type from the context. This is shorthand for
this.Database.Log = (delegate (string s){ System.Diagnostics.Debug.WriteLine(s); });
Which in turn is short hand for (as the other answers mention) creating a private method and assigning a delegate reference to that private method:
this.Database.Log = (Action<string>)__compiler_generated_function__;
private void __compiler_generated_function__(string s) {
System.Diagnostics.Debug.WriteLine(s);
}
It means assign a function to this.Database.Log. When this.Database.Log executes it finds the function
s => System.Diagnostics.Debug.WriteLine(s);
That stands for
void LogMethod(string s)
{
System.Diagnostics.Debug.WriteLine(s);
}
I read quite some articles about delegates, and yes, at first the syntax is confusing. I found this article the most useful. Example 2 makes it quite understandable how to use delegates. But I have this code given to me and have work with it:
public delegate bool IntPredicate(int x);
public delegate void IntAction(int x);
class IntList : List<int>
{
public IntList(params int[] elements) : base(elements)
{
}
public void Act(IntAction f)
{
foreach (int i in this)
{
f(i);
}
}
public IntList Filter(IntPredicate p)
{
IntList res = new IntList();
foreach (int i in this)
if (p(i))
res.Add(i);
return res;
}
}
Now, what confuses me here is the f and p variables in the Act and Filter functions. As in the tutorial, those functions seem to be normal, with normal type of their attributes, but here the attributes are of the delegate functions type and I get confusled.
Can you please enlighten me a bit on this matter?
A delegate is just a type. With the types you're used to (like int, string etc.), when you want to use them, you either use one that is in the framework or you declare your own. You can do exactly the same with delegates - either use a prebuilt one (like System.Action) or declare your own, which is what was done here.
So, in your code snippet, 3 types are declared:
public delegate bool IntPredicate(int x);
public delegate void IntAction(int x);
class IntList : List<int> { ... }
You'll notice that the delegate declarations are on the same level as the class declaration.
When you have a type (like your IntPredicate here), you can then use it for variables or function parameters. The questions now are: how do you set the value of the variable, and what do you do with it then?
With ordinary variables, you just pass in the value. Like this:
string text = "Hello world";
The principle is the same with delegates, but, of course, you have to pass in something that is of the delegate type or something that can be converted to it. You have several options:
Existing method
You can pass in a method, if its signature (that is, the return value and parameters) match those of the delegate. So, you could do this:
void WriteIntAction(int value)
{
Console.WriteLine(value);
}
/* then, in some other method */
IntList intList = new IntList(1,2,3);
intList.Act(WriteIntAction);
Anonymous method
There are several ways to create an anonymous method. I'm going to go with lambda expression, because that is simplest. If you've ever worked with any functional languages, this should be familiar.
IntList intList = new IntList(1,2,3);
intList.Act(x => Console.WriteLine(x));
So, after you have your variable set up with the method you need (whether existing or anonymous), you can simply use the delegate variable as you would any method. This is what this line does:
f(i);
Just be aware that delegate is a reference type, so the value of f here can be null, which will then throw an exception when you try to call a delegate.
TL;DR
A delegate is a type. You can use it in a variable or method parameter. You can pass a method in just using its name or you can create an anonymous method. You can then call the method you passed it by using the variable as you would a method.
You can read more online, for example here: http://msdn.microsoft.com/en-us/library/ms173171.aspx
A delegate type is, for all intents and purposes, just a function (or if you are a C++ user, akin to a function-pointer). In other words, you call them just as if they were a function, which is exactly what the sample code does.
f(i) calls the passed function with the i variable as its sole argument, just as it looks.
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
How can I pass an anonymous type to a method?
I have the following LINQ Statement, whose output has to be processed in another method:
var data = from lines in File.ReadAllLines(TrainingDataFile)
.Skip(ContainsHeader ? 1 : 0)
let f = lines.Split(new[] { FieldSeparator }).ToList<String>()
let target = f[TargetVariablePositionZeroBased]
select new { F=f, T=target };
What should be the datatype of the parameter in the method that will take this data?
You can not return the anonymous data types from a method. You can define a class and return object of that class from query and pass it to target method.
public class SomeClass
{
public string F {get; set;}
public string T {get; set;}
}
var data = from lines in File.ReadAllLines(TrainingDataFile)
.Skip(ContainsHeader ? 1 : 0)
let f = lines.Split(new[] { FieldSeparator }).ToList<String>()
let target = f[TargetVariablePositionZeroBased]
select new SomeClass { F=f, T=target };
You can pass the query result IEnumerable<SomeClass> to method as parameter.
public void MethodToCall(IEnumerable<SomeClass> someClass)
{
}
To call the method by passing the query result (IEnumerable<SomeClass>) that is stored in data in this sample code
MethodToCall(data);
You can't very easily pass anonymous types around. You can either create a class, or since your data has only two properties, use a Tuple:
select new Tuple<List<string>, string> (f, target);
If I have the data types correct, then the data type of the parameter would be:
IEnumerable<Tuple<List<string>, string>>
and you would reference F and T using the Tuple properties Item1 and Item2.
1) Just to pass the result of the query, make your function generic, that will do:
var data = from lines in File.ReadAllLines(TrainingDataFile)
.Skip(ContainsHeader ? 1 : 0)
let f = lines.Split(new[] { FieldSeparator }).ToList<String>()
let target = f[TargetVariablePositionZeroBased]
select new { F=f, T=target };
SomeMethod(data);
public void SomeMethod<T>(IEnumerable<T> enumerable)
{
// ^^choose the return type..
}
Simple. If the processing inside the method is something so simple this will do. But you won't be able to access properties F and T inside the method.
To do so:
2) You can use the "cast by example" trick shown here by Eric. To quote him:
We use method type inference and local variable type inference to tell
the compiler "these two things are the same type". This lets you
export an anonymous type as object and cast it back to anonymous type.
...the trick only works if the example and the source objects were
created in code in the same assembly; two "identical" anonymous types
in two different assemblies do not unify to be the same type.
SomeMethod(data);
public void SomeMethod(IEnumerable<object> enumerable)
{
var template = new { F = new List<string>(), T = string.Empty };
foreach (var item in enumerable)
{
var anonymousType = item.CastToTypeOf(template);
//print string.Join(", ", anonymousType.F) + " - " + anonymousType.T //compiles
//or whatever
}
}
//a more generic name perhaps is 'CastToTypeOf' as an extension method
public static T CastToTypeOf<T>(this object source, T example) where T : class
{
return (T)source;
}
The catch here is that SomeMethod now is tailor made for your anonymous type, since you're specifying a specific type inside the method, so its better to not make the function generic (though you can do) and to give a suitable name for the function.
3) If function is just for your unique type now, I would better have them all wrapped in a single method and not pass at all - no hassle! :)
4) Or you can delegate the action to be done on your anonymous type. So method signature would be like:
SomeMethod(data, d => print string.Join(", ", d.F) + " - " + d.T);
public void SomeMethod<T>(IEnumerable<T> enumerable, Action<T> actor)
{
foreach (var item in enumerable)
actor(item);
}
If it matters you can have Func delegate as well by having one more type argument.
5) Rely on fiddly reflection to get the properties from your anonymous type otherwise.
6) Use dynamic keyword on method argument and now you have dynamic typing. Both the above doesnt give you benefits of static typing.
7) You will be better off having a separate class that holds F and T. And that the best of all. But ask yourself do they together represent something as an entity?
8) If not, just pass an IEnumerable<Tuple> or IDictionary depending on what matters.
It all depends on what/how you want to achieve with the method. Personally, I would go for the approach 2 in a hobby project (for the fun involved), but in production code 3, 4, 7, 8 depending on the context.
void MyMethod(string something, params object[] parameters)
{
foreach (object parameter in parameters)
{
// Get the name of each passed parameter
}
}
For example, if I call the method in the following way, I want to get the names "myFirstParam" and "anotherParam".
string myFirstParam = "some kind of text";
string anotherParam = 42;
MyMethod("test", myFirstParam, anotherParam);
Perhaps reflection is the answer? Perhaps it's just not possible? I am aware of the existance of this question, but that solution won't work here.
(Please do not respond with "This is not a good idea". That is not my question.)
This is totally impossible.
Here are just a few cases where it doesn't even make sense:
MyMethod("abc", new object[5]);
MyMethod("abc", "def");
MyMethod("abc", var1 + var2);
MyMethod("abc", SomeMethod());
MyMethod("abc", b ? a : c);
MyMethod("abc", new object());
MyMethod("abc", null);
In fact, local variable names aren't even compiled into the assembly.
Building on #shingo's answer.
Since C#10, you can get the name of the variable passed using CallerArgumentExpressionAttribute Class.
This is .NET6:
using System.Runtime.CompilerServices;
void F(object arg1, [CallerArgumentExpression("arg1")] string arg1Exp = "?")
=> Console.WriteLine($"{arg1Exp} => {arg1}");
var var1 = "C#10";
var var2 = "_";
var b = var1.Length > 7;
F(var1);
F(new object[5]);
F("def");
F(var1 + var2);
F(SomeMethod());
F(b ? var1 : var2);
F(new object());
F(null);
F(int.Parse(var1.Substring(2)) switch {
>= 10 => "Supported",
_ => "Not supported"
});
int SomeMethod() => 7 + 8;
Output (which seems magical):
var1 => C#10
new object[5] => System.Object[]
"def" => def
var1 + var2 => C#10_
SomeMethod() => 15
b ? var1 : var2 => _
new object() => System.Object
null =>
int.Parse(var1.Substring(2)) switch {
>= 10 => "Supported",
_ => "Not supported"
} => Supported
C# 10 has introduced a new attribute CallerArgumentExpressionAttribute.
Getting names from params parameters is still impossible, but if you have fixed number of parameters (like overload methods), then it's possible.
void MyMethod(object p0,
[CallerArgumentExpression("p0") string p0exp = "p0")
{
Console.WriteLine(p0exp);
}
void MyMethod(object p0, object p1,
[CallerArgumentExpression("p0") string p0exp = "p0",
[CallerArgumentExpression("p1") string p1exp = "p1")
{
}
In addition to SLaks's answer - variable names are not available at run-time at all. The variables are represented by stack slots and are addressed by an index. Thus you can't get this information even for the example you provided, not to mention all these examples SLaks provided. Reflection is no help here. Nothing is.
It is not possible, and I wonder why you would need that.
I RAISE THIS QUESTION FROM THE DEAD!
Check out C# 6.0's new nameof() operator. It allows you to do exactly what you want, and it actually isn't always a bad idea.
A good use case is Argument Exceptions, or INotifyPropertyChanged. (Especially when you get inheritance in the mix)
Example:
interface IFooBar
{
void Foo(object bar);
}
public class FooBar : IFooBar
{
public void Foo(object bar)
{
if(bar == null)
{
//Old and Busted
//throw new ArgumentException("bar");
//The new HOTNESS
throw new ArgumentException(nameof(bar)); // nameof(bar) returns "bar"
}
//....
}
}
Now, if you were rename the parameter 'bar' on the method 'Foo' in the interface IFooBar, your argument exceptions would update accordingly (prevents you from forgetting to change the "bar" string)
Pretty neat actually!
What about this;
void MyMethod(string something, object parameters)
{
RouteValueDictionary dic = HtmlHelper.AnonymousObjectToHtmlAttributes(options);
}
MyMethod("test", new { #myFirstParam=""some kind of text", anotherParam=42);
This has already been implemented in System.Web.MVC.Html InputExtension.
I was inspired and using this technique in my code.
It is very flexible.
Dont bother about "Html" naming in the helper methods. There is nothing to do with html, or html attributes inside the helper method.
It just converts named, anonymous arguments to RouteValueDictionary, a special dictionary having IDictionary<string,object> interface where key holds the argument name and object is the value of the argument.
Using reflection, and #Martin's example of null argument testing:
using System.Reflection;
public SomeMethod(ClassA a, ClassB b, ClassC c)
{
CheckNullParams(MethodBase.GetCurrentMethod(), a, b, c);
// do something here
}
accessing the parameter names:
public void CheckNullParams(MethodBase method, params object[] args)
{
for (var i=0; i < args.Count(); i++)
{
if (args[i] == null)
{
throw new ArgumentNullException(method.GetParameters()[i].Name);
}
}
}
This works with constructors and public methods, but I haven't tested beyond unit tests within VS, so possibly there are some runtime JIT issues (reading through articles referenced above).
EDIT: Just noticed, this is essentially the same as linked answer.