On MSDN I found:
In C#, every executed instruction is done so in the context of a method.
But I also read that an int A=5; statement can be in the class body. It seems it's not in a method body, so why this is possible? It is probably just term confusion but I would like to know.
Adrian is correct. To clarify further: "int A = 5;" is only a statement when it is inside a method body. When it is outside a method body then it is a field declaration with an initializer, which is logically moved into the constructor body.
The exact semantics of how the initializers work is a bit tricky. For some thoughts on that, see:
http://blogs.msdn.com/b/ericlippert/archive/2008/02/15/why-do-initializers-run-in-the-opposite-order-as-constructors-part-one.aspx
http://blogs.msdn.com/b/ericlippert/archive/2008/02/18/why-do-initializers-run-in-the-opposite-order-as-constructors-part-two.aspx
class Example
{
int A = 5;
}
is equal to
class Example
{
int A;
public Example()
{
A = 5;
}
}
So the assignment is still part of a method (the constructor).
You are probably referring to field initializations:
class Foo
{
private static int i = 5;
}
Even this instruction runs inside the context of a method. In this particular case it is the static constructor. If the field is not static then it will be the normal constructor.
Related
I was under the impression that lambda expression contexts in C# contain references to the variables of the parent function scope that are used in them. Consider:
public class Test
{
private static System.Action<int> del;
public static void test(){
int i = 100500;
del = a => System.Console.WriteLine("param = {0}, i = {1}", a, i);
del(1);
i = 10;
del(1);
}
public static void Main()
{
test();
}
}
outputs
param = 1, i = 100500
param = 1, i = 10
However, if this was true, the following would be illegal, because the lambda context would reference a local variable that went out of scope:
public class Test
{
private static System.Action<int> del;
public static void test(){
int i = 100500;
del = a => System.Console.WriteLine("param = {0}, i = {1}", a, i);
}
public static void Main()
{
test();
del(1);
}
}
However, this compiles, runs and outputs
param = 1, i = 100500
Which means that either something weird is going on, or the context keeps values of the local variables, not references to them. But if this was true, it would have to update them on every lambda invokation, and I don't see how that would work when the original variables go out of scope. Also, it seems that this could incur an overhead when dealing with large value types.
I know that, for example, in C++, this is UB (confirmed in answer to this question).
The question is, is this well-defined behaviour in C#? (I think C# does have some UB, or at least some IB, right?)
If it is well-defined, how and why does this actually work? (implementation logic would be interesting)
The concept of closures as they relate to the lambda syntax in C# is a very large topic and too large for me to cover everything in just this answer but let's try to answer the specific question here at least. The actual answer is at the bottom, the rest between is background needed to understand the answer.
What happens when the compiler tries to compile a method using anonymous methods is that it rewrites the method to some extent.
Basically, a new class is generated and the anonymous method is lifted into this class. It's given a name, albeit an internal one, so for the compiler it sort of transitions from an anonymous method into a named method. You, however, doesn't have to know or handle that name.
Any variables that this method required, variables that was declared besides the anonymous method, but in the same method that used/declared the anonymous method, will be lifted as well, and then all usages of those variables is rewritten.
There's a couple of methods involved here now so it becomes hard to read the above text so instead let's do an example:
public Func<int, int> Test1()
{
int a = 42;
return value => a + value;
}
This method is rewritten to something like this:
public Func<int, int> Test1()
{
var dummy = new <>c__DisplayClass1();
dummy.a = 42;
return dummy.<Test1>b__0;
}
internal class <>c__DisplayClass1
{
public int a;
public int <Test1>b__0(int value)
{
return a + value;
}
}
The compiler can handle all these funky names (and yes, they really are named with all the brackets like that) because it refers to things with id's and object references, the names are no longer an issue for the compiler. You, however, can never declare a class or a method with those names so there's no risk of the compiler generating a class that just happens to already exist.
Here's a LINQPad example that shows that a class I declared, although with less brackets in its names, looks identical to the one generated by the compiler:
void Main()
{
var f1 = Test1();
f1(10).Dump();
f1.Dump();
var f2 = Test2();
f2(10).Dump();
f2.Dump();
}
public Func<int, int> Test1()
{
int a = 42;
return value => a + value;
}
public Func<int, int> Test2()
{
var dummy = new __c__DisplayClass1();
dummy.a = 42;
return dummy._Test2_b__0;
}
public class __c__DisplayClass1
{
public int a;
public int _Test2_b__0(int value)
{
return a + value;
}
}
output:
If you look at the screenshot above you notice two things for each delegate variable, a Method property, and a Target property.
When calling the method, it is called with a this reference referring to the Target object. A delegate thus captures two things: Which method to call, and the object on which to call it.
So basically, that object of that generated class survives as part of the delegate because it is the target of the method.
With all that in mind, let's look at your question:
Why does a lambda expression preserve enclosing scope variable values after method terminates?
A: If the lambda survives, all the captured variables survive as well because they're no longer local variables of the method they were declared in. Instead they were lifted onto a new object that also has the lambda method, and thus "follows" the lambda everywhere it goes.
I was thinking of List's functionality and not thinking about the fact that Count() was an extension method when I made the false assumption that I could write a class having a same named property and method. The motivation in my mind at the time was I could "parameterize a property" for special cases.
I realize now that I can do it, provided I utilize an extension method.
Is this intentionally disallowed in classes but allowed in extensions or simply a non-existant feature?
void Main()
{
var list = new List<string>();
// You compile code that gets the property named Count
// and calls the method named Count()
list.Add("x");
Console.WriteLine (list.Count);
list.Add("x");
Console.WriteLine (list.Count());
var c = new C();
Console.WriteLine (c.Count);
Console.WriteLine (c.Count());
}
public class C
{
public int Count { get { return 3; } }
// But you cannot compile a class that contains both a property
// named Count and a method named Count()
//public int Count () { return 0; } // <-- does not compile
}
public static class X
{
public static int Count(this C c)
{
return 4;
}
}
I remember asking this question like 10 years ago on one of Microsoft groups:
http://www.developmentnow.com/g/36_2003_9_0_0_195928/methods-and-properties-of-the-same-name.htm
and as you can see there was no convincing answer.
This is of course easily possible in CIL, as properties translate to paris of getXX/setXX methods.
This is because Count(this C c) is an extension method and doesn't actually make a part of the type.
That means that you can have a method Count() in C + extension Count(). If you call it, will be called instance method.
So if we think about a property there is even less problems with that.
for example
Class AClass
{
public AClass (int a)
{...}
public void DoIt()
{
...
c = PreDo();
...
}
private int PreDo()
{ ...
if (b==1)
xxxxx
...
}
}
int Main ()
{
AClass myClass = new AClass(2);
myClass.DoIt(); //*
}
* Here I wanna once xxxx is called then myClass is no long useful.
Hence it would try out myClass = new AClass(3), myClass.DoIt() in the main instead, and so on.
accross all instances or only in one instance? ... just use a (static) variable notRunAllready to remember the called (so if (b==1) goes to if (!notRunAllready && b==1)) and you set notRunAllready to true in xxxx
May be I understood what you are talking about.
You probably want to make conditional execution based on some class internal variable wich initialized in class's constructor.
Declare them like a static like #CKoening says. But it's wired by we, cause it's not absolutely clear what will gonna happen during the call.
The best solution to make conditional execution is add parameters to your DoIt(..) method, by making esplicit "what is gonna be happen if I pass this parameter to the function".
If this is not what you're asking about, please explain better.
In the following code:
public class A
{
public A():this(null){}
public A(string b){/*code here*/}
}
What is the use of first constructor?
The first constructor is passing null into parameter b of the second constructor.
Thus if you call new A() it will be the same as calling new A(null)
When you have a constructor with a parameter
public A(string b){ /* code here */ }
public A():this("") { } //default
the default constructor actually calls the "parameter constructor" with "" as a parameter. You are passing a parameter. This is done in order to avoid writing the same code twice
It's a constructor overload.
I agree it doesn't seem to be very useful in this case because most likely the uninitialised value for a string is null anyway.
See also Constructors in C#
this happens when you're overloading constructors.
in your example the empty contructor public A():this(null){} looks for a constructor that can take in an object value of null. since a string is an object that can take nulls, it calls that constructor.
this example seems very simplistic.
a more meaningful example (but still keeping it basic):
public class AddNumbers
{
public AddNumbers():this(100, 100)
{ }
public AddNumbers(int x, int y)
{
int sum = x + y;
Console.WriteLine(sum.ToString());
}
}
in this example, when a calling program calls the empty constructor, it will output 200. because it is calling the AddNumbers method with x = 100, y = 100.
i know it's a simple example but i hope that makes it clearer.
It's a default constructor that calls second with b==null.
Some interfaces or designers require there to be a "parameterless" constructor.
This method comes in handy in those times.
Having a parameterless default constructor is required when object initialization is used:
Employee e = new Employee() {FirstName="John", LastName="Smith"};
In this case, I probably would not use constructor chaining, though. Constructor overloading gives you an alternative way to initialize with parameters. Where constructor chaining is really useful is in making constructor parameters optional; C# doesn't support optional parameters (yet).
"Best practice" will depend on the situation, usage, architecture, requirements, etc. (ISO Consulting Rule Number One: "It depends.")
I am getting into C# and I am having this issue:
namespace MyDataLayer
{
namespace Section1
{
public class MyClass
{
public class MyItem
{
public static string Property1{ get; set; }
}
public static MyItem GetItem()
{
MyItem theItem = new MyItem();
theItem.Property1 = "MyValue";
return theItem;
}
}
}
}
I have this code on a UserControl:
using MyDataLayer.Section1;
public class MyClass
{
protected void MyMethod
{
MyClass.MyItem oItem = new MyClass.MyItem();
oItem = MyClass.GetItem();
someLiteral.Text = oItem.Property1;
}
}
Everything works fine, except when I go to access Property1. The intellisense only gives me "Equals, GetHashCode, GetType, and ToString" as options. When I mouse over the oItem.Property1, Visual Studio gives me this explanation:
MemberMyDataLayer.Section1.MyClass.MyItem.Property1.getcannot be accessed with an instance reference, qualify it with a type name instead
I am unsure of what this means, I did some googling but wasn't able to figure it out.
In C#, unlike VB.NET and Java, you can't access static members with instance syntax. You should do:
MyClass.MyItem.Property1
to refer to that property or remove the static modifier from Property1 (which is what you probably want to do). For a conceptual idea about what static is, see my other answer.
You can only access static members using the name of the type.
Therefore, you need to either write,
MyClass.MyItem.Property1
Or (this is probably what you need to do) make Property1 an instance property by removing the static keyword from its definition.
Static properties are shared between all instances of their class, so that they only have one value. The way it's defined now, there is no point in making any instances of your MyItem class.
I had the same issue - although a few years later, some may find a few pointers helpful:
Do not use ‘static’ gratuitously!
Understand what ‘static’ implies in terms of both run-time and compile time semantics (behavior) and syntax.
A static entity will be automatically constructed some time before
its first use.
A static entity has one storage location allocated, and that is
shared by all who access that entity.
A static entity can only be accessed through its type name, not
through an instance of that type.
A static method does not have an implicit ‘this’ argument, as does an
instance method. (And therefore a static method has less execution
overhead – one reason to use them.)
Think about thread safety when using static entities.
Some details on static in MSDN:
Static Classes in C#
Static Constructors in C#
This causes the error:
MyClass aCoolObj = new MyClass();
aCoolObj.MyCoolStaticMethod();
This is the fix:
MyClass.MyCoolStaticMethod();
Explanation:
You can't call a static method from an instance of an object. The whole point of static methods is to not be tied to instances of objects, but instead to persist through all instances of that object, and/or to be used without any instances of the object.
No need to use static in this case as thoroughly explained. You might as well initialise your property without GetItem() method, example of both below:
namespace MyNamespace
{
using System;
public class MyType
{
public string MyProperty { get; set; } = new string();
public static string MyStatic { get; set; } = "I'm static";
}
}
Consuming:
using MyType;
public class Somewhere
{
public void Consuming(){
// through instance of your type
var myObject = new MyType();
var alpha = myObject.MyProperty;
// through your type
var beta = MyType.MyStatic;
}
}
cannot be accessed with an instance reference
It means you're calling a STATIC method and passing it an instance. The easiest solution is to remove Static, eg:
public static void ExportToExcel(IEnumerable data, string sheetName)
{
Remove the static in the function you are trying to call. This fixed the problem for me.
I got here googling for C# compiler error CS0176, through (duplicate) question Static member instance reference issue.
In my case, the error happened because I had a static method and an extension method with the same name. For that, see Static method and extension method with same name.
[May be this should have been a comment. Sorry that I don't have enough reputation yet.]
I know this is an old thread, but I just spent 3 hours trying to figure out what my issue was. I ordinarily know what this error means, but you can run into this in a more subtle way as well. My issue was my client class (the one calling a static method from an instance class) had a property of a different type but named the same as the static method. The error reported by the compiler was the same as reported here, but the issue was basically name collision.
For anyone else getting this error and none of the above helps, try fully qualifying your instance class with the namespace name. ..() so the compiler can see the exact name you mean.
Check whether your code contains a namespace which the right most part matches your static class name.
Given the a static Bar class, defined on namespace Foo, implementing a method Jump or a property, chances are you are receiving compiler error because there is also another namespace ending on Bar. Yep, fishi stuff ;-)
If that's so, it means your using a Using Bar; and a Bar.Jump() call, therefore one of the following solutions should fit your needs:
Fully qualify static class name with according namepace, which result on Foo.Bar.Jump() declaration. You will also need to remove Using Bar; statement
Rename namespace Bar by a diffente name.
In my case, the foollowing compiler error occurred on a EF (Entity Framework) repository project on an Database.SetInitializer() call:
Member 'Database.SetInitializer<MyDatabaseContext>(IDatabaseInitializer<MyDatabaseContext>)' cannot be accessed with an instance reference; qualify it with a type name instead MyProject.ORM
This error arouse when I added a MyProject.ORM.Database namespace, which sufix (Database), as you might noticed, matches Database.SetInitializer class name.
In this, since I have no control on EF's Database static class and I would also like to preserve my custom namespace, I decided fully qualify EF's Database static class with its namepace System.Data.Entity, which resulted on using the following command, which compilation succeed:
System.Data.Entity.Database.SetInitializer<MyDatabaseContext>(MyMigrationStrategy)
Hope it helps
YourClassName.YourStaticFieldName
For your static field would look like:
public class StaticExample
{
public static double Pi = 3.14;
}
From another class, you can access the staic field as follows:
class Program
{
static void Main(string[] args)
{
double radius = 6;
double areaOfCircle = 0;
areaOfCircle = StaticExample.Pi * radius * radius;
Console.WriteLine("Area = "+areaOfCircle);
Console.ReadKey();
}
}