public void MethodSample1(Itest variable)
{
variable.TestString = "some sample data";
Itest var1 = variable;
Console.WriteLine(variable.TestString);
MethodSample2(variable);
Console.WriteLine(variable.TestString);
Console.WriteLine(var1.TestString);
}
public void MethodSample2(Itest variable)
{
variable.TestString = "testdata";
}
public interface Itest
{
string TestString { get; set; }
}
Expected both the console output lines print "some sample data" but it seems that TestString is being overwritten with the new value? is it not like "by default in C# all the values are passed by value?".
In short, how to preserve the value of "TestString" in MethodSample1?
(I ran into this problem because all my projects are based upon a single interface)
Even after preserving the value, it does reflect! strange!
For your current problem, I don't think you can prevent any method from modifying the parameter passed to it.
Your variable is a reference type object, In C# reference type's address is passed by value to a method, that is why you are seeing the change. For example if your method is written like:
public void MethodSample2(Itest variable)
{
variable = null;
}
You won't see the change in your MethodSample1 method, since the reference address is passed by value.
is it not like "by default in C# all the values are passed by
value?".
Value types are passed by value, in your case variable is a reference type.
You should see Parameter Passing C# by Jon Skeet
Not sure why you have to modify the passed object, For workaround you can create a temporary copy of the property and then set that value before existing from the method.
The parameter is indeed passed by value, but the value you are passing is a reference to the original object.
If you want to preserve the original object's properties, you'll need to pass a copy of the original object. You could add a Clone() method to the interface or something similar:
public interface ITest
{
string TestString { get; set; }
ITest Clone();
}
public class Test : ITest
{
string TestString { get; set; }
ITest Clone() {
return new Test() {
TestString = this.TestString
};
}
}
Or, you could rethink your current approach. Do you really need to change the property of the interface? Or could you use a variable of type string instead?
how to preserve the value of "TestString" in MethodSample1?
Store it in a local variable.
public void MethodSample1(Itest variable)
{
variable.TestString = "some sample data";
string localTestString = variable.TestString;
Console.WriteLine(variable.TestString);
MethodSample2(variable);
variable.TestString = localTestString;
Console.WriteLine(variable.TestString);
}
But, this is wrong way of doing things. If you tell a little more what do you want to achieve, we could help more.
Related
I have an Interface
interface IPerson
{
PersonInformation PersonInfo { get; set; }
}
And this class
public class PersonInformation
{
public string Name{ get; set; }
}
When I implement the interface it's giving me a null error and I can't determine why. My get/set looks correct
class Employee: MyStore, IPerson
{
private PersonInformation _perInfo;
public override void Execute()
{
PersonInfo.Name = "Bill";
}
public PersonInformation PersonInfo
{
get
{
return _perInfo;
}
set
{
_perInfo = value;
}
}
}
Everything compiles but when I try to set PersonInfo.Name it's saying the object isn't set. I've played around with the get/set in the interface but that didn't change anything. I'm thinking I'm missing something so obvious...any ideas???
Just declaring a reference variable member does not create an object for that variable. You must set the variable to refer to an actual object instance.
So you either want this:
myEmployee.PersonInfo = new PersonInformation();
myEmployee.PersonInfo.Name = "Some Name";
or this in the class definition:
private PersonInformation _perInfo = new PersonInformation();
// ...
myEmployee.PersonInfo.Name = "Some Name";
As a further note, in the latter case you probably would be better off having the set be private, or not even defining it at all. (Note the interface definition will require otherwise, but I expect you can change that, too).
This is because setting a mere property like .Name is still a get operation on the parent object: first you get the reference to the entire PersonInformation object, and then use the set on the object's .Name property to set the field.
You only need to use a set for this property if you want to replace the entire object with a different one (see, for example, the first line in my sample above).
Possible this question seems duplicate but I explored stackoverflow article but noone gives answer to question.
I am trying to understand string data type behave. As we know string is immutable and reference data type.
So when we are passing a reference type parameter and change value in calling method , we get changes intact in caller method like as below code. e.g. we have user object which is passing as argument to a method "show" and this method change the value of user object and we get updated value in main method.This is happening as user is reference type.
When we passed string data type which is also reference type and immutable to print method and change value , we do not get updated value of string variable in main method.
Why this is behaving different than user object.?
When we passed string with ref parameter , we get updated value in main method. Here it is behaving like pass by ref.
So, string behaves like pass by value by default but this is pass by reference indeed, Why?
public class test
{
public void Show(User user)
{
user.id = 2;
user.Name = "Change";
}
public void Print(string test)
{
test = "new name";
}
}
public class User
{
public int id { get; set; }
public string Name { get; set; }
}
Main method
User user = new User { id = 1, Name = "New" };
test test = new test();
test.Show(user);
string name = "old name";
test.Print(name);
I read c-sharp-string this and most reply is stating that two variables are pointing to same location. so if it is, then change to one value should reflect in both places.
Under the hood objects are just pointers so when you pass in an object as an argument you are essentially copying the address of the instance into the function. So when you change the parameters of the passed object you are changing the parameters of the original instance. Now if you want to edit an int that is being passed as an argument you need to use the ref keyword. Also it might be interesting how this:
public void Show(User user)
{
user.id = 2;
user.Name = "Change";
user = null;
}
Will change the parameters of the object but the user object won't be set to null. That is because we are only changing our local pointer to the instance in memory instead of actually changing the pointer we passed. But if we passed this using the ref keyword this would set the original instance we had in main to null.
I may think string is called reference type. Because in C# when there are two string with same values or you have two strings and copy the value of one string to another. I will logically be not copied, until unless you change the value of second string. The second string will point to the same location as the first one. And in the above program you passed string as a value (am i write in this? no keyword ref is used, string is by default reference type, but if it is passed in parameter like this, and value change in original string then how can you be able to avoid reference of string while passing it in the parameter. (String is logically called reference typed : recommending a book, Read in that with detail will give you more knowledge about string data type in strings chapter.)
I understand struct is value type. But I do not understand why it behave like this?
Is it because i didn't treat it as immutable? or is it has something to do with the auto property?
using System;
namespace StructQuestion
{
class Program
{
static StructType structAsProperty { get; set; }
static StructType structAsField;
static void Main(string[] args)
{
structAsProperty.InjectValue("structAsProperty");
structAsField.InjectValue("structAsField");
//debugger says structAsProperty.GetValue() is null
Console.WriteLine(structAsProperty.GetValue());
Console.WriteLine(structAsField.GetValue());
Console.ReadLine();
}
}
public struct StructType
{
private string value;
public void InjectValue(string _value)
{
value = _value;
}
public string GetValue()
{
return value;
}
}
}
Let's look at what happens in this statement:
structAsProperty.InjectValue("structAsProperty");
We don't have to go far. The very first thing that must happen is to resolve the structAsProperty part of the statement. The key here is understanding the compiler re-writes property get and set sections as a method calls behind the scenes.
So what we really have here is a call to a method that returns our struct value. I say "value" here rather than "object" because structs are value types. With value types, passing to or returning from a method results in a copy of the value.
Now we know enough to understand what happened. We are calling InjectValue() on a copy of the property struct, not the instance in the property itself. Next we modify this copy via it's InjectValue() method... and then promptly forget the copy ever existed.
You can fix it like this:
var prop = structAsProperty; //now we have a variable to keep the result of the implicit get accessor method
prop.InjectValue("structAsProperty");
structAsProperty = prop;
Is it possible to get value without creating an instance ?
I have this class:
public class MyClass
{
public string Name{ get{ return "David"; } }
public MyClass()
{
}
}
Now I need get the value "David", without creating instance of MyClass.
Real answer: no. It's an instance property, so you can only call it on an instance. You should either create an instance, or make the property static as shown in other answers.
See MSDN for more information about the difference between static and instance members.
Tongue-in-cheek but still correct answer:
Is it possible to get value without creating an instance ?
Yes, but only via some really horrible code which creates some IL passing in null as this (which you don't use in your property), using a DynamicMethod. Sample code:
// Jon Skeet explicitly disclaims any association with this horrible code.
// THIS CODE IS FOR FUN ONLY. USING IT WILL INCUR WAILING AND GNASHING OF TEETH.
using System;
using System.Reflection.Emit;
public class MyClass
{
public string Name { get{ return "David"; } }
}
class Test
{
static void Main()
{
var method = typeof(MyClass).GetProperty("Name").GetGetMethod();
var dynamicMethod = new DynamicMethod("Ugly", typeof(string),
Type.EmptyTypes);
var generator = dynamicMethod.GetILGenerator();
generator.Emit(OpCodes.Ldnull);
generator.Emit(OpCodes.Call, method);
generator.Emit(OpCodes.Ret);
var ugly = (Func<string>) dynamicMethod.CreateDelegate(
typeof(Func<string>));
Console.WriteLine(ugly());
}
}
Please don't do this. Ever. It's ghastly. It should be trampled on, cut up into little bits, set on fire, then cut up again. Fun though, isn't it? ;)
This works because it's using call instead of callvirt. Normally the C# compiler would use a callvirt call even if it's not calling a virtual member because that gets null reference checking "for free" (as far as the IL stream is concerned). A non-virtual call like this doesn't check for nullity first, it just invokes the member. If you checked this within the property call, you'd find it's null.
EDIT: As noted by Chris Sinclair, you can do it more simply using an open delegate instance:
var method = typeof(MyClass).GetProperty("Name").GetGetMethod();
var openDelegate = (Func<MyClass, string>) Delegate.CreateDelegate
(typeof(Func<MyClass, string>), method);
Console.WriteLine(openDelegate(null));
(But again, please don't!)
You can make that property static
public static string Name{ get{ return "David"; } }
Usage:
MyClass.Name;
You requirements do seem strange, but I think you're looking for some kind of metadata. You can use an attribute to achieve this:
public class NameAttribute : Attribute {
public string Name { get; private set; }
public NameAttribute(string name) {
Name = name;
}
}
[Name("George")]
public class Dad {
public string Name {
get {
return NameGetter.For(this.GetType());
}
}
}
[Name("Frank")]
public class Son : Dad {
}
public static class NameGetter {
public static string For<T>() {
return For(typeof(T));
}
public static string For(Type type) {
// add error checking ...
return ((NameAttribute)type.GetCustomAttributes(typeof(NameAttribute), false)[0]).Name;
}
}
Now this code can get names with and without instances:
Console.WriteLine(new Dad().Name);
Console.WriteLine(new Son().Name);
Console.WriteLine(NameGetter.For<Dad>());
Console.WriteLine(NameGetter.For<Son>());
You can make your property static, as pointed out by many others.
public static string Name{ get{ return "David"; } }
Be aware that this means your instances of MyClass will no longer have their own Name property, since static members belong to the class, not the individual object instances of it.
Edit:
In a note, you mentioned that you want to override the Name property in subclasses. At the same time, you want to be able to access it at the class level (access it without creating an instance of your class).
For the static properties, you would simply create a new Name property in each class. Since they are static, you're always (almost always, yay reflection) going to access them using a specific class, so you'd be specifying which version of Name you want to get. If you want to try and hack polymorphism in there and get the name from any given subclass of MyClass, you could do so using reflection, but I wouldn't recommend doing so.
Using the example from your comment:
public class Dad
{
public static string Name { get { return "George"; }
}
public class Son : Dad
{
public static string Name { get{ return "Frank"; }
}
public static void Test()
{
Console.WriteLine(Dad.Name); // prints "George"
Console.WriteLine(Son.Name); // prints "Frank"
Dad actuallyASon = new Son();
PropertyInfo nameProp = actuallyASon.GetType().GetProperty("Name");
Console.WriteLine(nameProp.GetValue(actuallyASon, null)); // prints "Frank"
}
As a side note, since you are declaring a property that has only a getter and it is returning a constant value, I recommend possibly using a const or static readonly variable instead.
public const string Name = "David";
public static readonly string Name = "David";
Usage for both would be the same:
string name = MyClass.Name;
The main benefit (and drawback) of const is that all references to it are actually replaced by its value when the code is compiled. That means it will be a little faster, but if you ever change its value, you will need to recompile ALL code that references it.
Whenever you write C# code, always check if your method and property getter/setter code does anything at all with other instance members of the class. If they don't, be sure to apply the static keyword. Certainly the case here, it trivially solves your problem.
The reason I really post to this question is that there's a bit of language bias at work in some of the answers. The C# rule that you can't call an instance method on a null object is a specific C# language rule. It is without a doubt a very wise one, it really helps to troubleshoot NullReferenceExceptions, they are raised at the call site instead of somewhere inside of a method where it gets very hard to diagnose that the this reference is null.
But this is certainly not a requirement to the CLR, nor of every language that run on the CLR. In fact, even C# doesn't enforce it consistently, you can readily bypass it in an extension method:
public static class Extensions {
public static bool IsNullOrEmpty(this string obj) {
return obj != null && obj.Length > 0;
}
}
...
string s = null;
bool empty = s.IsNullOrEmpty(); // Fine
And using your property from a language that doesn't have the same rule works fine as well. Like C++/CLI:
#include "stdafx.h"
using namespace System;
using namespace ClassLibrary1; // Add reference
int main(array<System::String ^> ^args)
{
MyClass^ obj = nullptr;
String^ name = obj->Name; // Fine
Console::WriteLine(name);
return 0;
}
Create a static property:
public class MyClass
{
public static string Name { get { return "David"; } }
public MyClass()
{
}
}
Get it like so:
string name1 = MyClass.Name;
That is not possible. As Name is an instance property, you can only get its value if you have an instance.
Also, note that you are not talking about a parameter, but about a property.
Create a static class or a static property, and you don't have to explicitly instantiate it.
I'd like semantics similar to C#'s ref keyword.
Java is confusing because everything is passed by value. However for a parameter of reference type (i.e. not a parameter of primitive type) it is the reference itself which is passed by value, hence it appears to be pass-by-reference (and people often claim that it is). This is not the case, as shown by the following:
Object o = "Hello";
mutate(o)
System.out.println(o);
private void mutate(Object o) { o = "Goodbye"; } //NOT THE SAME o!
Will print Hello to the console. The options if you wanted the above code to print Goodbye are to use an explicit reference as follows:
AtomicReference<Object> ref = new AtomicReference<Object>("Hello");
mutate(ref);
System.out.println(ref.get()); //Goodbye!
private void mutate(AtomicReference<Object> ref) { ref.set("Goodbye"); }
Can I pass parameters by reference in
Java?
No.
Why ? Java has only one mode of passing arguments to methods: by value.
Note:
For primitives this is easy to understand: you get a copy of the value.
For all other you get a copy of the reference and this is called also passing by value.
It is all in this picture:
In Java there is nothing at language level similar to ref. In Java there is only passing by value semantic
For the sake of curiosity you can implement a ref-like semantic in Java simply wrapping your objects in a mutable class:
public class Ref<T> {
private T value;
public Ref(T value) {
this.value = value;
}
public T get() {
return value;
}
public void set(T anotherValue) {
value = anotherValue;
}
#Override
public String toString() {
return value.toString();
}
#Override
public boolean equals(Object obj) {
return value.equals(obj);
}
#Override
public int hashCode() {
return value.hashCode();
}
}
testcase:
public void changeRef(Ref<String> ref) {
ref.set("bbb");
}
// ...
Ref<String> ref = new Ref<String>("aaa");
changeRef(ref);
System.out.println(ref); // prints "bbb"
From James Gosling in "The Java Programming Language":
"...There is exactly one parameter passing mode in Java - pass by value - and that keeps things simple.
.."
I don't think you can. Your best option might be to encapsulate the thing you want to pass "by ref" onto another class instance, and pass the (outer) class's reference (by value). If you see what I mean...
i.e. your method changes the internal state of the object it is passed, which is then visible to the caller.
Java is always pass by value.
When you pass a primitive it's a copy of the value, when you pass an object it's a copy of the reference pointer.
Another option is to use an array, e.g.
void method(SomeClass[] v) { v[0] = ...; }
but 1) the array must be initialized before method invoked, 2) still one cannot implement e.g. swap method in this way...
This way is used in JDK, e.g. in java.util.concurrent.atomic.AtomicMarkableReference.get(boolean[]).
Check out my response in: http://stackoverflow.com/a/9324155/1676736
In there I used a simpler version of the wrapper class idea.
I don't like setters/getters as a standard. When there is no reason to bury a field I make it 'public'. Especially in something like this.
However, this would work for all but the primitive, or multi-parameter/type returns:
public class Ref<T> {
public T val;
}
Although, I suppose you could just add more type parameters. But I think that creating an inner static class fit-for-purpose would be easier:
public static class MyReturn {
public String name;
public int age;
public double salary;
}
this would be for use when you don't need it for other reasons.
MyReturn mRtn = new MyReturn();
public void myMethod(final MyReturn mRtn){
mRtn.name = "Fred Smith";
mRtn.age = 32;
mRtn.salary = 100000.00;
}
System.out.println(mRtn.name + " " +mRtn.age + ": $" + mRtn.salary);