This question already has answers here:
Why use the 'ref' keyword when passing an object?
(10 answers)
Closed 7 years ago.
the following code does not work as I would expect:
using System;
using System.Data;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
MyClass cl = new MyClass();
cl.doSomething();
}
}
public class MyClass : BaseClass
{
protected override void doSelect(DataTable dt)
{
dt = null;
}
public void doSomething()
{
base.Fill();
}
}
public class BaseClass
{
private DataTable dtMain = null;
protected virtual void doSelect(DataTable dt)
{
}
protected void Fill()
{
dtMain = new DataTable();
this.doSelect(dtMain);
if (dtMain == null)
Console.WriteLine("as I would expect");
else
Console.WriteLine("why not changed???");
}
}
}
I tested it with other reference types, but same behavior. Is this a framework bug? When I use the ref keyword it works as I expect:
protected virtual void doSelect(ref DataTable dt)
{
} and so on
Would be nice I anyone could help me with this!
Consider following
class Program
{
static void Main(string[] args)
{
var pr = new Program();
f(pr);
if (pr == null)
Console.WriteLine("Can't happen");
else
Console.WriteLine("Always happen");
}
public static void f(Program prog)
{
prog = null;
}
}
pr variable references to some memory address, let's say namely 0x111111. When you call f method, what really happens is that, prog variable is assigned to same value as pr e.i 0x111111 . when you assign null to prog variable, it makes prog variable to points to null but not pr variable content, nor content stored in 0x111111 is changed. So, pr variable still references to 0x111111 memory address. Same happens in your case.
When you do not use the ref keyword, the parameter is passed by value. If you change the value (i.e. the reference) to refer something else (here null), then that is not reflected on the caller's side.
This is not really related to your use of virtual and override.
An alternative to ref here is to return the new value (instead of returning void), as in:
protected virtual DataTable doSelect(DataTable dt)
{ /* ... */ }
Be sure your method name reflects what the method does.
When doSelect() assigns null to dt, it merely changes the value of the pointer in it's stack frame. However, Fill() has it's own stack frame with it's own "copy" of dtMain. This value had not been changed by doSelect().
Passing a value by ref means passing a pointer to the value inside the caller's (Fill()) stack frame.
It's not a bug.
That's expected behaviour.
Unless you use the ref keyword, you are passing by value, so the value on the "client" side of the method won't change.
Read the MS reference for the ref keyword:
https://msdn.microsoft.com/en-us/library/14akc2c7.aspx
Related
This question already has answers here:
How to call an appropriate method by string value from collection?
(3 answers)
Closed 3 years ago.
I have 1000 methods called method0001, method0002 , ... ,method1000.
I have a variable that takes values between 1 and 1000.
If the value of the variable is x, I'd like to call methodx. For instance, if the value of the variable is 34, I'd like to call method0034. How can I code this in C# please?
Many people are asking what is need for Methodwxyz. Every method is a different type of math question.
i've done this, following the helpful comments but am getting errors (edited the question from earlier)
using System.Collections.Generic;
using UnityEngine;
public class TextControl : MonoBehaviour
{
public static TextControl instance;
void Start()
{
instance = this;
}
// Update is called once per frame
void Update()
{
this.GetType().GetMethod("Template00" + "1").Invoke(this, null);
}
public static string Templates001()
{
// doing something here
}
}
thanks
You could do this through reflection. Edit for a quick sample (forgot invoke parameters). Some tips about reflection:
If you get a nullexception that means it can't find the method
The method you are invoking needs to be public
If you use obfuscation you may not have the same names for the method
Code
public class Program
{
public static void Main(string[] args)
{
Check method1 = new Check(1);
Check method2 = new Check(2);
}
}
public class Check
{
public Check(int x)
{
this.GetType().GetMethod("Method" + x).Invoke(this, null);
}
public void Method1()
{
Console.WriteLine("Method 1");
}
public void Method2()
{
Console.WriteLine("Method 2");
}
}
When I am updating my obj as null its output is 30 but no exception but when I am updating obj.Age = 25 output is 25.
I am not getting the idea what is happening behind the scene.
Can someone explain why this is happening?
public class A
{
public int age;
}
class Program
{
public static void Test(A obj)
{
//obj = null;
//obj.age = 25;
}
static void Main(string[] args)
{
try
{
A obj = new A();
obj.age = 30;
Test(obj);
Console.WriteLine(obj.age);
}
catch (Exception)
{
throw;
}
}
}
Notice the method signature -
public static void Test(A obj)
The parameter is not passed as ref. When the reference types are passed as parameter, without specifying as ref. You can change the properties values within the object, but you cannot assign the object to point it to another memory location.
In simple words you cannot do -
obj = null OR obj = new A() OR obj = instanceOfAnotherObject
To be able to even change the object, you need to change the method signature and pass obj by ref -
public static void Test(ref A obj)
When you do obj = null; then you do not set the object to null but the reference to that object to null. As in your method Test the parameter is a new reference to the passed object, it does not affect the obj reference in Main and so setting obj to null in Test has only an effect in that method.
To do / see what you want you may want to change the parameter of Test to a ref parameter like so
public static void Test(ref A obj)
and then call Test like so
...
A obj = new A();
obj.age = 30;
Test(ref obj);
...
as now you actually modify the obj reference of the Main method.
When you do obj.age = 25; in Test (of course without setting obj to null in front of it) then you modify the same object as obj in Main points to and so when writing the age to the console you will see 25.
That is possible because it was passed by reference - if you replace A with e.g. int and pass that around then changing its value in Test will not be reflected in the output of Main as integers are passed by value. You may find reading this page and the subsequent pages to it helpful
I've this question about pass some instances by ref or not: here is my problem:
Case 1: simple var like int:
private void button2_Click(object sender, EventArgs e)
{
int nTest = 10;
testInt(nTest);
MessageBox.Show(nTest.ToString());
// this message show me 10
testIntRef(ref nTest);
MessageBox.Show(nTest.ToString());
// this message show me 11
}
private void testInt(int nn)
{
nn++;
}
private void testIntRef(ref int nn)
{
nn++;
}
this is exactly what I think, if I use the ref, the parameter is passed by reference, so if is changed, when I exit from the function, the value is changed...
Case 2: class:
// simple class to understand the reference..
public class cTest
{
int nTest;
public cTest()
{
setTest(0);
}
public void setTest(int n)
{
nTest = n;
}
public int getTest()
{
return nTest;
}
}
// my main code
private void button3_Click(object sender, EventArgs e)
{
cTest tt = new cTest();
tt.setTest(2);
testClass(tt);
// I expect that the message shows me 2, 'cause testClass
// doesn't have (ref cTest test)
MessageBox.Show(tt.getTest().ToString());
}
private void testClass(cTest test)
{
test.setTest(55);
}
and, as written in the comment on the code, I don't have passed my cTest as reference, but the result is the same, the message show me 55 and not 2..
How can I pass a class without reference?
How can I pass a class without reference?
You can't.
You can clone that instance and send it, but it will still be sent by ref...
class - Reference type
struct - Value type.
Reading:
Article about passing variables in C#
Wikipedia about Objects copy- shallow copy + deep copy.
Quoting Jon Skeet C# in depth second edition:
MYTH #3: “OBJECTS ARE PASSED BY REFERENCE IN C# BY DEFAULT”
This is probably the most widely propagated myth. Again, the people who make this
claim often (though not always) know how C# actually behaves, but they don’t know
what “pass by reference” really means. Unfortunately, this is confusing for people who
do know what it means. The formal definition of pass by reference is relatively complicated,
involving l-values and similar computer science terminology, but the important
thing is that if you pass a variable by reference, the method you’re calling can change
the value of the caller’s variable by changing its parameter value. Now remember that the
value of a reference type variable is the reference, not the object itself. You can change
the contents of the object that a parameter refers to without the parameter itself being
passed by reference.
For instance, the following method changes the contents of the
StringBuilder object in question, but the caller’s expression will still refer to the
same object as before:
void AppendHello(StringBuilder builder)
{
builder.Append("hello");
}
When this method is called, the parameter value (a reference to a StringBuilder) is
passed by value. If I were to change the value of the builder variable within the
method—for example, with the statement builder = null;—that change wouldn’t be
seen by the caller, contrary to the myth.
C# in depth Value types and reference types page 46
If you want something like that, you want to use struts instead of classes.
If you just want to make sure that a method can't modify an argument, then you can create a read-only base class:
public abstract class ReadOnlyUser
{
public string GetName() { ... }
}
public class User : ReadOnlyUser
{
public void SetName(string name) { ... }
}
Then you can write the method in such a way that the method body can't modify the argument by mistake:
public void Register(ReadOnlyUser user)
{
string name = user.GetName();
user.SetName("John"); // doesn't compile
}
Of course you can invoke this method with an instance of the User class:
var user = new User(...);
Register(user);
You can also implement a read-only interface:
public interface IReadOnlyUser
{
string GetName();
}
public interface IUser : IReadOnlyUser
{
void SetName(string name);
}
public class User : IUser
{
public string GetName() { ... }
public void SetName(string name) { ... }
}
public void Register(IReadOnlyUser user)
{
string name = user.GetName();
user.SetName("John"); // doesn't compile
}
I'm having a problem with C#, I'd like to get a pointer of a method in my code, but it seems impossible. I need the pointer of the method because I want to no-op it using WriteProcessMemory. How would I get the pointer?
Example code
main()
{
function1();
function2();
}
function1()
{
//get function2 pointer
//use WPM to nop it (I know how, this is not the problem)
}
function2()
{
Writeline("bla"); //this will never happen because I added a no-op.
}
I know this is very old, but an example of something like a function pointer in C# would be like this:
class Temp
{
public void DoSomething() {}
public void DoSomethingElse() {}
public void DoSomethingWithAString(string myString) {}
public bool GetANewCat(string name) { return true; }
}
...and then in your main or wherever:
var temp = new Temp();
Action myPointer = null, myPointer2 = null;
myPointer = temp.DoSomething;
myPointer2 = temp.DoSomethingElse;
Then to call the original function,
myPointer();
myPointer2();
If you have arguments to your methods, then it's as simple as adding generic arguments to your Action:
Action<string> doItWithAString = null;
doItWithAString = temp.DoSomethingWithAString;
doItWithAString("help me");
Or if you need to return a value:
Func<string, bool> getACat = null;
getACat = temp.GetANewCat;
var gotIt = getACat("help me");
EDIT: I misread your question and didn't see the bit about wanting to NOP a statement with doing raw memory manipulation. I'm afraid this isn't recommended because, as Raymond Chen says, the GC moves stuff around in memory (hence the 'pinned' keyword in C#). You probably can do it with reflection, but your question suggests you don't have a strong grasp of the CLR. Anyway, back to my original irrelevant answer (where I thought you just wanted information on how to use delegates):
C# isn't a scripting language ;)
Anyway, C# (and the CLR) has "function pointers" - except they're called "delegates" and are strongly typed, which means you need to define the function's signature in addition to the function you want to call.
In your case, you'd have something like this:
public static void Main(String[] args) {
Function1();
}
// This is the "type" of the function pointer, known as a "delegate" in .NET.
// An instance of this delegate can point to any function that has the same signature (in this case, any function/method that returns void and accepts a single String argument).
public delegate void FooBarDelegate(String x);
public static void Function1() {
// Create a delegate to Function2
FooBarDelegate functionPointer = new FooBarDelegate( Function2 );
// call it
functionPointer("bla");
}
public static void Function2(String x) {
Console.WriteLine(x);
}
public string myFunction(string name)
{
return "Hello " + name;
}
public string functionPointerExample(Func<string,string> myFunction)
{
return myFunction("Theron");
}
Func functionName.. use this to pass methods around. Makes no sense in this context but thats basically how you would use it
I'd wish it is useful
class Program
{
static void Main(string[] args)
{
TestPointer test = new TestPointer();
test.function1();
}
}
class TestPointer
{
private delegate void fPointer(); // point to every functions that it has void as return value and with no input parameter
public void function1()
{
fPointer point = new fPointer(function2);
point();
}
private void function2()
{
Console.WriteLine("Bla");
}
}
Actually there are real function pointers introduced in C# 9
Official Documentation
From the link:
You can define a function pointer using the delegate* syntax. The compiler will call the function using the calli instruction rather than instantiating a delegate object and calling Invoke
Example for the example in the post:
static unsafe void function1()
{
//get function2 pointer
delegate*<void> ptr = &function2;
// do something with ptr
}
Rewriting a method cannot be done directly from managed code, however the unmanaged .net profiling api can be used to do this. See this msdn article for example on how to use it.
Consider the following code:
using System;
namespace ConsoleApplication2
{
class Program
{
static void Main(string[] args)
{
var square = new Square(4);
Console.WriteLine(square.Calculate());
}
}
class MathOp
{
protected MathOp(Func<int> calc) { _calc = calc; }
public int Calculate() { return _calc(); }
private Func<int> _calc;
}
class Square : MathOp
{
public Square(int operand)
: base(() => _operand * _operand) // runtime exception
{
_operand = operand;
}
private int _operand;
}
}
(ignore the class design; I'm not actually writing a calculator! this code merely represents a minimal repro for a much bigger problem that took awhile to narrow down)
I would expect it to either:
print "16", OR
throw a compile time error if closing over a member field is not allowed in this scenario
Instead I get a nonsensical exception thrown at the indicated line. On the 3.0 CLR it's a NullReferenceException; on the Silverlight CLR it's the infamous Operation could destabilize the runtime.
It was a compiler bug that has been fixed. The code should never have been legal in the first place, and if we were going to allow it, we should have at least generated valid code. My bad. Sorry about the inconvenience.
It's not going to result in a compile-time error because it is a valid closure.
The problem is that this is not initialized yet at the time the closure is created. Your constructor hasn't actually run yet when that argument is supplied. So the resulting NullReferenceException is actually quite logical. It's this that's null!
I'll prove it to you. Let's rewrite the code this way:
class Program
{
static void Main(string[] args)
{
var test = new DerivedTest();
object o = test.Func();
Console.WriteLine(o == null);
Console.ReadLine();
}
}
class BaseTest
{
public BaseTest(Func<object> func)
{
this.Func = func;
}
public Func<object> Func { get; private set; }
}
class DerivedTest : BaseTest
{
public DerivedTest() : base(() => this)
{
}
}
Guess what this prints? Yep, it's true, the closure returns null because this is not initialized when it executes.
Edit
I was curious about Thomas's statement, thinking that maybe they'd changed the behaviour in a subsequent VS release. I actually found a Microsoft Connect issue about this very thing. It was closed as "won't fix." Odd.
As Microsoft says in their response, it is normally invalid to use the this reference from within the argument list of a base constructor call; the reference simply does not exist at that point in time and you will actually get a compile-time error if you try to use it "naked." So, arguably it should produce a compile error for the closure case, but the this reference is hidden from the compiler, which (at least in VS 2008) would have to know to look for it inside the closure in order to prevent people from doing this. It doesn't, which is why you end up with this behaviour.
How about this:
using System;
using System.Linq.Expressions;
namespace ConsoleApplication2
{
class Program
{
static void Main(string[] args)
{
var square = new Square(4);
Console.WriteLine(square.Calculate());
}
}
class MathOp
{
protected MathOp(Expression<Func<int>> calc) { _calc = calc.Compile(); }
public int Calculate() { return _calc(); }
private Func<int> _calc;
}
class Square : MathOp
{
public Square(int operand)
: base(() => _operand * _operand)
{
_operand = operand;
}
private int _operand;
}
}
Have you tried using () => operand * operand instead? The issue is that there's no certainty that _operand will be set by the time you call the base. Yes, it's trying to create a closure on your method, and there's no guarantee of the order of things here.
Since you're not setting _operand at all, I'd recommend just using () => operand * operand instead.