This question already has an answer here:
Get Reference to Field from Reflection [duplicate]
(1 answer)
Closed 2 years ago.
I need to get a reference to a field value in C# but I cant find any way to get an actual reference to the field that can be passed as a parameter. Any help will be greatly appreciated.
Example:
public class SomeClass
{
public int value = 0;
}
public class SomeOtherClass
{
static void Main(string[] args)
{
SomeClass x = new SomeClass();
Console.WriteLine(x.value); //Outputs "0"
foreach (FieldInfo field in x.GetType().GetFields())
{
Log(ref field.value) //Outputs "10"
} // ^
} //Not a valid member
static void Log(ref int i)
{
i = 10;
Console.WriteLine(i);
}
}
Try the below
public class SomeClass
{
public int value = 0;
}
public class SomeOtherClass
{
public static void Main(string[] args)
{
SomeClass x = new SomeClass();
Console.WriteLine(x.value); // Output Line 1
foreach (FieldInfo field in x.GetType().GetFields())
{
Console.WriteLine(field.GetValue(x)); // Output Line 2
var y = (int)field.GetValue(x);
Log(ref y);
Console.WriteLine(y); // Output Line 4
}
}
static void Log(ref int i)
{
i = 10;
Console.WriteLine(i); // Output Line 3
}
}
Output:
0
0
10
10
class Program
{
public class SomeClass
{
public int value = 0;
}
public class SomeOtherClass
{
static void Main(string[] args)
{
var x = new SomeClass();
Console.WriteLine(x.value); //Outputs "0"
foreach (FieldInfo field in x.GetType().GetFields())
{
var value = (int)field.GetValue(x);
Log(ref x);
Console.WriteLine(x.value);
}
}
static void Log(ref SomeClass x)
{
x.value = 10;
}
}
}
Related
Thanks to the kind folks who answered my previous question from a few days ago, I now know how to pass arguments by reference:
static void Main()
{
int i = 0;
Add(ref i, 100);
// now i == 100
}
static void Add(ref int arg, int increment)
{
arg += increment;
}
But is there a way for me not to just pass i by reference, but actually store its location in another variable? By that I mean use i like I did in my example; affecting the original instance, but in a way that's permanently linked and not leaving scope.
I vaguely know that I could use a pointer to determine the location in unsafe context but I was wondering if I could do this without any of that, or if it is just recommended to use the unsafe method.
If you are using C# 7 you can use ref local and ref return to store an updateable reference to any field.
In this example I change the private field _privateField from 0 to 100 from outside Foo, the class in which it is defined, by returning it as a ref int and updating it by reference.
class Foo
{
private int _privateField = 0;
public ref int GetReference()
{
return ref _privateField;
}
public override string ToString()
{
return _privateField.ToString();
}
}
public class Program
{
public static void Main()
{
var foo = new Foo();
var referenceToPrivateField = foo.GetReference();
referenceToPrivateField = 100;
Console.WriteLine(foo);
}
}
Prior to that, you'd have to store the value in a field contained in an object, and pass around a reference to the object instead.
In this example I change the value from 0 to 100 from outside Foo, even though it is stored (indirectly) in a field that is private inside the Foo instance.
class ValueTypeReference<T> where T : struct
{
public T Value { get; set; }
}
class Foo
{
private ValueTypeReference<int> _privateField = new ValueTypeReference<int>{ Value = 0 };
public ValueTypeReference<int> GetReference()
{
return _privateField;
}
public override string ToString()
{
return _privateField.Value.ToString();
}
}
public class Program
{
public static void Main()
{
var foo = new Foo();
var referenceToPrivateField = foo.GetReference();
referenceToPrivateField.Value = 100;
Console.WriteLine(foo);
}
}
Output:
100
Well, if I udnerstood you correctly, you want the variable to have global scope, which can be achieved by putting variable as class field/property:
class Program
{
private static int _i;
static void Main()
{
_i = 0;
Add(100);
// now _i == 100
}
static void Add(int increment)
{
_i += 100;
}
}
I am newbie in C# and trying to learn static keyword. I don't understand why we need to initialize static field twice. as my understanding static field preserve the value during the program execution.
class Program
{
static void Main(string[] args)
{
AttemptController Obj = new AttemptController(3, 2);
Console.WriteLine("Maximum: {0}", AttemptController.MaxAttempts);
Console.WriteLine("Warning: {0}", AttemptController.WarningAttempts);
Console.WriteLine("Threshold: {0}", AttemptController.Threshold);
AttemptController Obj1 = new AttemptController(7, 5);
Console.WriteLine("Maximum: {0}", AttemptController.MaxAttempts);
Console.WriteLine("Warning: {0}", AttemptController.WarningAttempts);
Console.WriteLine("Threshold: {0}", AttemptController.Threshold);
Console.ReadLine();
}
class AttemptController
{
internal static int MaxAttempts;
internal static int WarningAttempts;
internal static int Threshold;
public AttemptController(int a, int b)
{
MaxAttempts = a;
WarningAttempts = b;
Threshold = MaxAttempts - WarningAttempts;
}
}
}
So a couple of proposed changes:
make the class static
get rid of the constructor as static classes cannot have instance constructors.
add a new method called init just for demo purposes.
using System;
namespace ConsoleApp4
{
internal class Program
{
private static void Main(string[] args)
{
AttemptController.Init(3, 2);
Console.WriteLine("Maximum: {0}", AttemptController.MaxAttempts);
Console.WriteLine("Warning: {0}", AttemptController.WarningAttempts);
Console.WriteLine("Threshold: {0}", AttemptController.Threshold);
AttemptController.Init(7, 5);
Console.WriteLine("Maximum: {0}", AttemptController.MaxAttempts);
Console.WriteLine("Warning: {0}", AttemptController.WarningAttempts);
Console.WriteLine("Threshold: {0}", AttemptController.Threshold);
Console.ReadLine();
}
}
public static class AttemptController
{
internal static int MaxAttempts;
internal static int WarningAttempts;
internal static int Threshold;
public static void Init(int a, int b)
{
MaxAttempts = MaxAttempts + a;
WarningAttempts = WarningAttempts + b;
Threshold = MaxAttempts - WarningAttempts;
}
}
}
Because you set MaxAttempts,WarningAttempts,Threshold fields in the constructor method.
When you use AttemptController Obj = new AttemptController(3, 2); it will set the value.
when you use will set MaxAttempts = 3 and WarningAttempts = 2
AttemptController Obj = new AttemptController(3, 2);
when you use will set MaxAttempts = 7 and WarningAttempts = 5
AttemptController Obj1 = new AttemptController(7, 5);
static fields let all instance use the same fields value.
i have created a class person which is having functions add,sub,mul
and mytest where i am passing my delegate reference
and in static void main i want if
DateTime.Now.Hour<12 it should call add if DateTime.Now.Hour<20 it should call sub.
but i am getting error
'ad1' does not exist in current context
class person
{
public void add(int x,int y)
{
Console.WriteLine(x+y);
}
public void sub(int x,int y)
{
Console.WriteLine(x-y);
}
public void mul(int x,int y)
{
Console.WriteLine(x*y);
}
public void test(mydel ad1)
{
ad1(2, 3);
}
}
class Program
{
static void Main(string[] args)
{
person p = new person();
if(DateTime.Now.Hour<12)
{
mydel ad1 = p.add;
}
else if(DateTime.Now.Hour<20)
{
mydel ad1 = p.sub;
}
p.test(ad1);
}
}
ad1 is declared inside the if block in the Main method and doesn't exists outside the if scope.
I don't think you need this variable at all just call directly from within the if:
static void Main(string[] args)
{
person p = new person();
if(DateTime.Now.Hour<12)
{
p.test(p.add);
}
else if(DateTime.Now.Hour<20)
{
p.test(p.sub);
}
}
This will also ensure that when Hour > 20 nothing will be called, and you won't get a null exception.
If you do however choose to use this variable, define it before the if (and assign it with null) and ensure it's not null before you use it.
class person
{
public void add(int x, int y) => Console.WriteLine(x + y);
public void sub(int x, int y) => Console.WriteLine(x - y);
public void mul(int x, int y) => Console.WriteLine(x * y);
public void test(Action<int, int> ad1) => ad1(2, 3);
}
class Program
{
static void Main(string[] args)
{
person p = new person();
Action<int, int> action = (x, y) => {};
if (DateTime.Now.Hour < 12)
{
action = p.add;
}
else if (DateTime.Now.Hour < 20)
{
action = p.sub;
}
p.test(action);
}
}
I'm just starting out and I have a question. How do I call a public void?
e.g.
int x, y = 2;
namespace Blah
{
public class blah blah
{
public void count
{
Console.WriteLine("Hi: " + y);
}
public void counting
{
z = x * y
}
}
}
P.S: I have tried this How do I call a non-static method from a static method in C#? and it doesn't work for me
If it's a non-static class, you need to instantiate it first.
Then to call its void methods, justCallThem().
public class blahblah
{
int x, y = 2; // this sets y as 2, but x is not set
public void count()
{
Console.WriteLine("Hi: " + y);
}
public void counting()
{
int z = x * y;
Console.WriteLine("Z = {0}", z);
}
}
class Program
{
static void Main(string[] args)
{
blahblah b = new blahblah(); //instantiate the object
b.count(); //call a method on the object
b.counting();
Console.ReadKey();
}
}
// output:
// Hi: 2
// z = 0
You just need to call the method by the class object reference.
// Blah is a namespace
namespace Blah
{
// blah is the class name
public class blah
{
// x, y and z are member variables.
int x, y = 2;
int z = 0;
// SayHiis a public static method. Thus it dont requires the 'blah' object to call this method.
public static void SayHi()
{
Console.WriteLine("Hi: " + y);
}
// counting is a public non static method. Thus it requires the 'blah' object to call this method.
public void counting()
{
z = x * y;
}
}
}
// CallingMethod is the method where you want to call the counting method of class 'blah'
public void CallingMethod()
{
// As said above, you need a object to call the 'counting' method.
blah objBlah = new blah();
// Now call the non static method using this object.
objBlah.counting();
// and here you can directly call the non-static method SayHi like,
blah.SayHi();
}
I am trying to call a value from a method called GetInputstring from inside Main() method, and proceed to the next steps.
I am stuck regards to how I could get the value myInt and move along.
myInt (where it has two * around) inside Main() is where it gets the errors.
static void Main(string[] args)
{
GetInputstring(**myInt**);
if (**myInt** <= 0)
{
Write1(**myInt**);
}
else
{
Write2(**myInt**);
}
Console.ReadKey();
}
public int GetInputstring(int myInt)
{
string myInput;
//int myInt;
Console.Write("Please enter a number: ");
myInput = Console.ReadLine();
myInt = Int32.Parse(myInput);
return myInt;
}
static void Write1(int myInt)
{
while (myInt <= 0)
{
Console.WriteLine("{0}", myInt++);
}
}
static void Write2(int myInt)
{
while (myInt >= 0)
{
Console.WriteLine("{0}", myInt--);
}
}
MyInt is your parameter(the value you pass to your method) and it's not initialized. Further you don't catch your return value (which should be myInt)
You also need to make your methods static in order to call them from a static method or you create an instance of the class and invoke the method on it
That's how you'll get what you want:
static void Main(string[] args)
{
int myInt = GetInputstring(); //MyInt gets set with your return value
if (myInt <= 0)
{
Write1(myInt);
}
else
{
Write2(myInt);
}
Console.ReadKey();
}
public static int GetInputstring() //Deleted parameter because you don't need it.
{
string myInput;
//int myInt;
Console.Write("Please enter a number: ");
myInput = Console.ReadLine();
int myInt = Int32.Parse(myInput);
return myInt;
}
You need to initialize your myInt variable and store it in the local or global scope. With this variable you will need to set it with the value you get from GetInputString() because you are not passing the int as a ref it will not be assigned in the method. You also need to make your methods static so they can be called from Main without creating an instance, Ex: public static int GetInputstring()
int myInt = 0;
myInt = GetInputstring(myInt);
if (myInt <= 0)
{
Write1(myInt);
}
else
{
Write2(myInt);
}
Console.ReadKey();
Alternatively (And preferably), you could make GetInputString() assign the value because it dosen't need myInt to be passed as an parameter.
static void Main(string[] args)
{
int myInt = GetInputstring();
if (myInt <= 0)
{
Write1(myInt);
}
else
{
Write2(myInt);
}
Console.ReadKey();
}
public static int GetInputstring()
{
Console.Write("Please enter a number: ");
string myInput = Console.ReadLine();
return Int32.Parse(myInput);
}