Necessity of 'static' in methods that get parameters by reference - c#

I'm programming in C# about 2 months, and I've been noticing to the fact that the only way a method will get a parameter by reference is when the method sets as a static method, and I don't understand the reason behind this situation. As example, in C++ we could just send parameters by reference to any kind of method we wanted to.
Thanks ahead :)
I'm adding a very simple code for those who asked for:
public void f(ref int num)
{
num++;
}
private static void Main(string[] args)
{
int a = 0;
f(ref a);
Console.WriteLine(a);
Console.Read();
}
the error I get:
An object reference is required for the non-static field, method, or property
now, I know that in C# almost everything that not int, string, double... and other built-in vars are send automatically by ref. I wonder why the method must be static in case of sending those vars by ref.

the only way a method will get a parameter by reference is when the method sets as a static method
That's incorrect. C# has a concept of Reference Types and Value Types, where both are passed by value, but that value differs. For reference types, the value that gets passed is the reference itself, where for value types it's a copy of the value.
If you want a value type by reference, you can use the ref modifier in the methods signature:
public void M(ref int x)
Same goes for reference type, only for the fact that passing them by ref will pass the current reference pointing to the data structure, and won't create a copy of that reference.

You are not able to use f because it's an instance method and the Main is a static one so you cannot call it from here without having an instance of the class that contains f (I guess Program).
You need to either create an instance of Program:
this is exaclty the same as what the error message says:
An object reference is required for the non-static field, method, or property
so you create an object reference to Program:
class Program
{
public void f(ref int num)
{
num++;
}
private static void Main(string[] args)
{
int a = 0;
var p = new Program();
p.f(ref a);
Console.WriteLine(a);
Console.Read();
}
}
or make the method static to be able to use it:
class Program
{
public static void f(ref int num)
{
num++;
}
private static void Main(string[] args)
{
int a = 0;
f(ref a); // is the same as: Program.f(ref a)
Console.WriteLine(a);
Console.Read();
}
}
The ref keyword has nothing to do with it. It's all about how you call the method - via an object reference or as a static one without an object reference. Neither is better then the other. It's a design decision and each serves different puposes.

Related

Variable Scope For an Extension Method

I have something interesting that I want to understand little deeper.
I have an extension class that extends int:
public static class MyExtension
{
public static void GetProp(this int i, MyObject o)
{
var val = i;
o.sum = i;
}
}
That uses a class as one of its parameter:
public class MyObject
{
public int sum { get; set; }
}
Now, lets see the unit test class:
[TestClass]
public class UnitTest1
{
[TestMethod]
public void test()
{
int a = 1;
int b = 2;
int sum = 0;
Add(a, b, sum);
//Here, sum=3 but after its execution, sum looses its value and
retains the value sum = 0
int test = 4;
MyObject obj = new MyObject();
test.GetProp(obj);
But in the above code when I pass the variable using the extension
method, the obj.sum retains its value obj.sum = 4 . I am not passing any
value by reference. The first portion of code seems to follow the
passing ByVal. But the second portion of extension method, the value
is retained as if its passed as ByRef
string s = sum.ToString();
string p = obj.sum.ToString();
}
private void Add(int x, int y, int sum)
{
sum = x + y;
}
}
Can someone explain the mechanism behind this. Thanks
All parameters are send by value, unless you specify them with the ref or out keyword. Passing a parameter by value means that the value is copied.
However, when you pass an object by value it's not the object that is copied, it's the reference that is copied. That means that you have two references to the same object, one in the obj variable and one in the o parameter, but only one object.
When the extension method accessed the object, it's the same object as outside the method. Any change to the property made using the o parameter will be visible when you later access it using the obj variable.
This is the difference between passing by reference and passing a reference object (class). In GetProp, you aren't modifying the reference obj, you are modifying the MyObject instance that is referred by obj.
If I understand your question, you're confused about why the sum variable isn't changed when it is passed by value, but the obj.sum property does retain its value when obj is passed by reference. The other answers do a good job of explaining this.
In your question, you pass a parameter by value as a receiver, and this confuses your question a bit. Your question appears to be, "why is it that when I pass normally, it's treated as by-value, but when I pass as a receiver to an extension method, it's by-reference?"
Ah. Try assigning a new value to the receiver and see what happens at the call site:
public static void GetProp(this int i, MyObject o)
{
o.sum = i;
i = 5000;
}
You'll find that the variable test at the call site is not affected by this, since the receiver is also passed by value!

Reference type v. Value type

I have a question. When I do a
Int32 ii = new Int32();
am I creating a value type of a reference type with the identifier "ii?" If I'm creating a reference type, then how is it that when I pass a copy of that reference to a method that changes it's value, I don't see the changes when the method returns? When I run the code below I get "0."
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
Int32 ii = new Int32();
changeit(ii);
Console.WriteLine(ii.ToString());
Console.ReadLine();
}
static void changeit (Int32 i)
{
i = 2;
}
static void changeit(ref int i)
{
i = 2;
}
}
}
The new operator has a different meaning for value and reference types. For reference types, it means to allocate on the heap and initialize the type; for value types it means initialize only. So
int i=new int();
is the same as
int i=0;
See C# reference as a starter.
If I'm creating a reference type
You aren't creating a reference type. Using new doesn't change value type to a reference type.
static void Main(string[] args)
{
Int32 ii = new Int32();
changeit1(ii);
Console.WriteLine(ii.ToString());
changeit2(ref ii);
Console.WriteLine(ii.ToString());
Console.ReadLine();
}
static void changeit1(Int32 i)
{
i = 2;
}
static void changeit2(ref int i)
{
i = 2;
}
Results:
0
2
Int32 is by definition a value type. A type can be a value type or reference type by definition, you can't change it.
If you want your Int32 to be modified, you should pass it with the "ref" keyword:
static void changeit(ref int i)
{
i = 2;
}
The only way to acomplish something like that is encapsulating your Int32 inside a class, like:
public class DumbClass{
public int YourInt {get; set;}
}
When you put your integer as a property, you can change it, sending your DumbClass reference:
static void changeit(DumbClass c)
{
c.YourInt = 2;
}
This happens because classes are reference types (by definition).
Inside the hood, a lot of things happens. The framework may decide to allocate your variable in the stack or the heap depending os it's mood (because sometimes optimizations happens).
Usually when you declare an int inside a method, it's allocated on the stack and since it will be deallocated when the method finishes it's execution, it will be pretty weird if it is a reference type.
That's why there's the "boxing" and "unboxing" inside the framework. Sometimes value types are "boxed" so you can use it as reference types (and allocated on the managed heap). Personally, I don't know if there's a way to do it explicitly in C# and if it makes sense.

A object reference is required for the non-static field, method, or property 'Android.Support.V7.App.ActionBar.SetDisplayHomeAsUpEnabled(bool)' [duplicate]

This question already has answers here:
CS0120: An object reference is required for the nonstatic field, method, or property 'foo'
(9 answers)
Closed 5 years ago.
I'm creating an application in C#. Its function is to evaluate if a given is prime and if the same swapped number is prime as well.
When I build my solution in Visual Studio, it says that "an object reference is required for the non-static field, method or property...". I'm having this problem with the "volteado" and "siprimo" methods.
Where is the problem and how can I fix it?
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
Console.Write("Write a number: ");
long a= Convert.ToInt64(Console.ReadLine()); // a is the number given by the user
long av = volteado(a); // av is "a" but swapped
if (siprimo(a) == false && siprimo(av) == false)
Console.WriteLine("Both original and swapped numbers are prime.");
else
Console.WriteLine("One of the numbers isnt prime.");
Console.ReadLine();
}
private bool siprimo(long a)
{
// Evaluate if the received number is prime
bool sp = true;
for (long k = 2; k <= a / 2; k++)
if (a % k == 0) sp = false;
return sp;
}
private long volteado(long a)
{
// Swap the received number
long v = 0;
while (a > 0)
{
v = 10 * v + a % 10;
a /= 10;
}
return v;
}
}
}
You can't access non-static members from a static method. (Note that Main() is static, which is a requirement of .Net). Just make siprimo and volteado static, by placing the static keyword in front of them. e.g.:
static private long volteado(long a)
Create a class and put all your code in there and call an instance of this class from the Main :
static void Main(string[] args)
{
MyClass cls = new MyClass();
Console.Write("Write a number: ");
long a= Convert.ToInt64(Console.ReadLine()); // a is the number given by the user
long av = cls.volteado(a);
bool isTrue = cls.siprimo(a);
......etc
}
Simply add static in the declaration of these two methods and the compile time error will disappear!
By default in C# methods are instance methods, and they receive the implicit "self" argument. By making them static, no such argument is needed (nor available), and the method must then of course refrain from accessing any instance (non-static) objects or methods of the class.
More info on static methods
Provided the class and the method's access modifiers (public vs. private) are ok, a static method can then be called from anywhere without having to previously instantiate a instance of the class. In other words static methods are used with the following syntax:
className.classMethod(arguments)
rather than
someInstanceVariable.classMethod(arguments)
A classical example of static methods are found in the System.Math class, whereby we can call a bunch of these methods like
Math.Sqrt(2)
Math.Cos(Math.PI)
without ever instantiating a "Math" class (in fact I don't even know if such an instance is possible)
Change your signatures to private static bool siprimo(long a) and private static long volteado(long a) and see where that gets you.
You just need to make the siprimo and volteado methods static.
private static bool siprimo(long a)
and
private static long volteado(long a)
The error message means that you need to invoke volteado and siprimo on an instance of the Program class. E.g.:
...
Program p = new Program();
long av = p.volteado(a); // av is "a" but swapped
if (p.siprimo(a) == false && p.siprimo(av) == false)
...
They cannot be invoked directly from the Main method because Main is static while volteado and siprimo are not.
The easiest way to fix this is to make the volteado and siprimo methods static:
private static bool siprimo(long a)
{
...
}
private static bool volteado(long a)
{
...
}

Using delegates in C#

In C# language and .NET framework, could you help me with understanding delegates?
I was trying to check some code, and found that the results I received were unexpected for me. Here it is:
class Program
{
public static int I = 0;
static Func<string> del = new Func<string>(I.ToString);
static void Main(string[] args)
{
I = 10;
Console.WriteLine("{0}", del());
}
}
The answer was 0, but not 10. Why?
The reason is the following:
The way you declare the delegate it points directly to the ToString method of the static int instance. It is captured at the time of creation.
As flindeberg points out in the comments below, each delegate has a target and a method to be executed on the target.
In this case, the method to be executed is obviously the ToString method. The interesting part is the instance the method is executed on: It is the instance of I at the time of the creation, meaning that the delegate is not using I to get the instance to use but it stores the reference to the instance itself.
Later you change I to a different value, basically assigning it a new instance. This doesn't magically change the instance captured in your delegate, why should it?
To get the result you expect, you would need to change the delegate to this:
static Func<string> del = new Func<string>(() => I.ToString());
Like this, the delegate points to an anonymous method that executes ToString on the current I at the time of the execution of the delegate.
In this case, the method to be executed is an anonymous method created in the class in which the delegate is declared in. The instance is null as it is a static method.
Have a look at the code the compiler generates for the second version of the delegate:
private static Func<string> del = new Func<string>(UserQuery.<.cctor>b__0);
private static string cctor>b__0()
{
return UserQuery.I.ToString();
}
As you can see, it is a normal method that does something. In our case it returns the result of calling ToString on the current instance of I.
You need to pass in I to your function so that I.ToString() can be executed at the appropriate time (instead of at the time function is created).
class Program
{
public static int I = 0;
static Func<int, string> del = num => num.ToString();
static void Main(string[] args)
{
I = 10;
Console.WriteLine("{0}", del(I));
}
}
Here is how this should be done:
using System;
namespace ConsoleApplication1
{
class Program
{
public static int I = 0;
static Func<string> del = new Func<string>(() => {
return I.ToString();
});
static void Main(string[] args)
{
I = 10;
Console.WriteLine("{0}", del());
}
}
}
C# delegate enable encapsulate both an object and instance and a method. A delegate declaration defines a class that is derived from the class System.Delegate. A delegate instance encapsulates an invocations list, which is a list one or more method, each of which is referred to as callable entity.
learn more form
http://asp-net-by-parijat.blogspot.in/2015/08/what-is-delegates-in-c-how-to-declare.html
My guess is because int are passed by values not references, and for that reason when creating the delegate, it's a delegate to the method ToString of the current value of "I" (0).

Error: "an object reference is required for the non-static field, method or property..." [duplicate]

This question already has answers here:
CS0120: An object reference is required for the nonstatic field, method, or property 'foo'
(9 answers)
Closed 5 years ago.
I'm creating an application in C#. Its function is to evaluate if a given is prime and if the same swapped number is prime as well.
When I build my solution in Visual Studio, it says that "an object reference is required for the non-static field, method or property...". I'm having this problem with the "volteado" and "siprimo" methods.
Where is the problem and how can I fix it?
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
Console.Write("Write a number: ");
long a= Convert.ToInt64(Console.ReadLine()); // a is the number given by the user
long av = volteado(a); // av is "a" but swapped
if (siprimo(a) == false && siprimo(av) == false)
Console.WriteLine("Both original and swapped numbers are prime.");
else
Console.WriteLine("One of the numbers isnt prime.");
Console.ReadLine();
}
private bool siprimo(long a)
{
// Evaluate if the received number is prime
bool sp = true;
for (long k = 2; k <= a / 2; k++)
if (a % k == 0) sp = false;
return sp;
}
private long volteado(long a)
{
// Swap the received number
long v = 0;
while (a > 0)
{
v = 10 * v + a % 10;
a /= 10;
}
return v;
}
}
}
You can't access non-static members from a static method. (Note that Main() is static, which is a requirement of .Net). Just make siprimo and volteado static, by placing the static keyword in front of them. e.g.:
static private long volteado(long a)
Create a class and put all your code in there and call an instance of this class from the Main :
static void Main(string[] args)
{
MyClass cls = new MyClass();
Console.Write("Write a number: ");
long a= Convert.ToInt64(Console.ReadLine()); // a is the number given by the user
long av = cls.volteado(a);
bool isTrue = cls.siprimo(a);
......etc
}
Simply add static in the declaration of these two methods and the compile time error will disappear!
By default in C# methods are instance methods, and they receive the implicit "self" argument. By making them static, no such argument is needed (nor available), and the method must then of course refrain from accessing any instance (non-static) objects or methods of the class.
More info on static methods
Provided the class and the method's access modifiers (public vs. private) are ok, a static method can then be called from anywhere without having to previously instantiate a instance of the class. In other words static methods are used with the following syntax:
className.classMethod(arguments)
rather than
someInstanceVariable.classMethod(arguments)
A classical example of static methods are found in the System.Math class, whereby we can call a bunch of these methods like
Math.Sqrt(2)
Math.Cos(Math.PI)
without ever instantiating a "Math" class (in fact I don't even know if such an instance is possible)
Change your signatures to private static bool siprimo(long a) and private static long volteado(long a) and see where that gets you.
You just need to make the siprimo and volteado methods static.
private static bool siprimo(long a)
and
private static long volteado(long a)
The error message means that you need to invoke volteado and siprimo on an instance of the Program class. E.g.:
...
Program p = new Program();
long av = p.volteado(a); // av is "a" but swapped
if (p.siprimo(a) == false && p.siprimo(av) == false)
...
They cannot be invoked directly from the Main method because Main is static while volteado and siprimo are not.
The easiest way to fix this is to make the volteado and siprimo methods static:
private static bool siprimo(long a)
{
...
}
private static bool volteado(long a)
{
...
}

Categories