How can I pass an object of a "MyClass" (C#) by Parameter-by-Value to a method? example:
MyClass obj = new MyClass();
MyClass.DontModify(obj); //Only use it!
Console.Writeline(obj.SomeIntProperty);
...
public static void DontModify(MyClass a)
{
a.SomeIntProperty+= 100;// Do something more meaningful here
return;
}
By default object types are passed by value in C#. But when you pass a object reference to a method, modifications in the object are persisted. If you want your object to be inmutable, you need to clone it.
In oder to do it, implement the ICloneable interface in your class. Here is a mock example of how to use ICloneable:
public class MyClass : ICloneable
{
private int myValue;
public MyClass(int val)
{
myValue = val;
}
public void object Clone()
{
return new MyClass(myValue);
}
}
By default, it is passed by value. However, you're passing the object reference by value, which means you can still edit values within the object.
In order to prevent the object from being able to change at all, you would need to actually clone the object prior to passing it into your method. This would require you to implement some method of creating a new instance that is a copy of your original object, and then passing in the copy.
public static void DontModify(MyClass a)
{
MyClass clone = (MyClass)a.Clone();
clone.SomeIntProperty+= 100;// Do something more meaningful here
return;
}
You could create a Clone method on your object to pass the return value to your method. C# cannot pass reference types by value so this might be a good alternative.
public MyClass CreateClone()
{
return new MyClass() { SomeIntProperty = this.SomeIntProperty };
}
class Program
{
static void Main(string[] args)
{
Person p1 = new Person()
{
Name = "Alsafoo",
Address = new Address()
{
City = "Chicago"
}
};
Person p2 = new Person(p1.Address);
p2 = p1.GetClone(CloningFlags.Shallow);
p2.Name = "Ahmed";
p2.Address = new Address(){City = "Las Vegas"};
Console.WriteLine("p1 first name: {1} --- p1 city: {2} {0}p2 first name: {3} ---- p2 city: {4}",
Environment.NewLine, p1.Name, p1.Address.City, p2.Name, p2.Address.City);
Console.ReadKey();
}
}
public class Person
{
public Person()
{}
public Person(Address a)
{
Address = a;
}
public string Name { get; set; }
public Address Address { get; set; }
}
public class Address
{
public string City { get; set; }
}
Download this extension
https://www.nuget.org/packages/CloneExtensions/1.2.0
Created a Extention method
using System.Text.Json;
namespace Student.Utilities
{
public static class CloneExtension
{
public static T Clone<T>(this T cloneable) where T : new()
{
var toJson = JsonSerializer.Serialize(cloneable);
return JsonSerializer.Deserialize<T>(toJson);
}
}
}
Now, while calling, call it like this to pass the clone to another method:
public void CreateStudent(Student student)
{
Student clonedStudent = student.Clone<Student>();
_repository.CreateStudent(clonedStudent);
}
Related
Is there any way, using reflection, ConstructorInfo or System.Runtime.CompilerServices or something else, to get the variable name of the object being created?
Example:
public class MyObject
{
public MyObject()
{
// Should print "Creating funnyName"
Debug.Writeline("Creating {0}", MagicGetNameMethod());
}
}
public class MyClass
{
public MyObject funnyName = null;
public void MyMethod()
{
funnyName = new MyObject();
}
}
You can get the file path, line number and method name of the caller, which is probably more useful for timing info:
The following will print something like Creating MyMethod#c:\source\MyProgram.cs:15.
public class MyObject
{
public MyObject(
[CallerMemberName]string caller = null,
[CallerFilePathAttribute] string path = null,
[CallerLineNumber]int lineNumber = 0)
{
Console.WriteLine("Creating {0}", $"{caller}#{path}:{lineNumber}");
System.Reflection.
MethodBase.GetCurrentMethod();
}
}
public class MyClass
{
public MyObject funnyName = null;
public void MyMethod()
{
funnyName = new MyObject();
}
}
I am working with C# where I need to create a single method which can accept parameter as a class name.
like: -
Class A
{
public string name {get;set;}
}
Class B
{
public int age {get;set;}
}
Class C
{
public decimal salary {get;set;}
}
A function will call MethodABC based on some condition.
Function1(){
A obj = new A();
MethodaBC(obj);
}
Function2(){
B obj = new B();
MethodaBC(obj);
}
Function3(){
C obj = new C();
MethodaBC(obj);
}
Method definition is: -
Static MethodABC(....)
Within MethodABC, I need to do some operation based on which class object has been passed in MethodABC.
You can always use the activator class to help you.
Example:
Type type = typeof(MyClass);
MyClass instance = (MyClass)Activator.Create(type);
//method example
public void ClassGet(string MyClassName,string blabla)
{
object instance = Activator.Create(MyClassName);
}
// Call it like:
Gold g = new Gold();
g.ClassGet("MyClass", "blabla");
You can pass the class as object as well:
//method example
public void ClassGet(MyClass MyClassName,string blabla)
{
object instance = Activator.Create(MyClassName);
}
// Call it like:
Gold g = new Gold();
g.ClassGet(MyClass, "blabla");
I'm currently having trouble and I have no clue how to fix it.
I have 2 classes:
class A
{
public string MyParam { get; set; }
}
class B : A
{
public new string MyParam { get { return base.MyParam != null ? base.MyParam.Substring(1) : null; } }
}
When I try to access the B.MyParam it works when I have a the correct type, but in most of my methods I have a generic type
with :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ConsoleApplication1
{
class Program
{
public class A
{
public string MyParam { get; set; }
}
public class B : A
{
public new string MyParam
{
get { return base.MyParam != null ? base.MyParam.Substring(1) : null; }
}
}
public static void MyMethod<T>(T variable) where T : A
{
Console.WriteLine(variable.MyParam);//this print hello
Console.WriteLine((variable as B).MyParam);//this print ello (exactly what i want)
Console.WriteLine(typeof(T)); // this print ConsoleApplication1.Program+A
Console.WriteLine(variable.GetType()); // this print ConsoleApplication1.Program+B
// so i need something like that
Console.WriteLine((variable as variable.GetType()).MyParam); // this line is invalid
}
static void Main(string[] args)
{
A a = new B();
a.MyParam = "Hello";
Console.WriteLine(a.GetType());
MyMethod(a);
Console.ReadKey();
}
}
}
Is there a way to do it?
Thank you in advance.
EDIT: it seems that what i want is :
dynamic variable2 = Convert.ChangeType(variable, variable.GetType());
Console.WriteLine(variable2.MyParam);
Your code doesn´t make any sense. If A inherits from B you´ll need A to override the base-implementation for your property. So I´ll assume you should rethink your inheritance-chain.
You can use override for this. Thus when your variable-parameter is of your base-class (I renamed that to A) you´re calling the base-method, if it´s a derived instance (here B) you´re calling the override:
class A
{
public virtual string MyParam { get; }
}
class B : A // note here that B derives from A, not the other way round
{
public override string MyParam
{
get { return base.MyParam != null ? base.MyParam.Substring(1) : null; },
set { ... }
}
}
EDIT: While new intrduces a new member which (accidentally) has the same name (and signature) as the base-member it effectivly hides the base-member. Thus you effectivly have two members. Your only way to indicate which member should be used is by casting your instance to the desired class from which you need the implementation. However this somehow breaks the purpose of generics as the generic member has to know the exact types that are possible for the type-parameter.
Anyway this seems like broken design to me, as you´re actually creating a new member which has another meaning. So you should also give it a new name.
Based on your generic method, I think all you need is an interface.
public interface IMyParam
{
string MyParam { get; set; }
}
Your classes.
class A : IMyParam
{
public virtual string MyParam { get; set; }
}
class B : A
{
public override string MyParam
{
get { return base.MyParam != null ? base.MyParam.Substring(1) : null; }
}
}
And your method, won't need to be generic.
public void MyMethod(IMyParam variable)
{
// Your logic here, for example.
Console.WriteLine(variable.MyParam);
}
Calling your method.
A a = new A();
a.MyParam = "Hello";
B b = new B();
b.MyParam = "Hello";
A ab = new B();
ab.MyParam = "Hello";
MyMethod(a); // Prints Hello
MyMethod(b); // Prints ello
MyMethod(ab); // Prints ello
As I understand Func and Action; An Action does not return a value, and a Func does. In the below example I have a child class create an instance of "SomeContent" and pass a reference back to the parent class. My questions are:
Does this.ContentDelagate(content) pass by reference or by value?
In the below example, should I have used Func as I want a reference to an the instantiated SomeContent object? If so can you provide an example?
namespace DelegateTut
{
class Program
{
static void Main(string[] args)
{
TestClass myTest = new TestClass();
myTest.ContentDelagate += ContentDelegateHandler;
myTest.RunDel();
Console.Write("Press Enter to exit...\n");
Console.ReadLine();
}
public static void ContentDelegateHandler(SomeContent content) {
Console.WriteLine(content.ValueOne);
Console.WriteLine(content.ValueTwo);
}
}
}
public class TestClass {
public TestClass() { }
public Action<SomeContent> ContentDelagate { get; set; }
public void RunDel() {
SendContentToMainThread();
}
public void SendContentToMainThread() {
SomeContent content = new SomeContent {
ValueOne = "Hello",
ValueTwo = "World"
};
this.ContentDelagate(content);
}
}
public class SomeContent {
public String ValueOne { get; set; }
public String ValueTwo { get; set; }
public SomeContent() { }
}
Does this.ContentDelagate(content) pass by reference or by value?
This question is a little confusing. We are dealing with both a getter and a delegate as well. I think its clearer to show:
public void SendContentToMainThread()
{
SomeContent content = new SomeContent
{
ValueOne = "Hello",
ValueTwo = "World"
};
Action<SomeContent> myDel = ContentDelagate;//Property Get
myDel(content);//invoke delegate
Console.WriteLine(content.ValueOne);//refer to this below
}
The handler is called as part of the multicast delegate. The handler is being passed a class which is a reference type. In C# reference and value types are passed by value. The underlying value that is copied could be a value (value type) or a location in memory (reference type).
Because this is a reference type it has reference type behavior:
public static void ContentDelegateHandler(SomeContent content)
{
Console.WriteLine(content.ValueOne);
Console.WriteLine(content.ValueTwo);
content.ValueOne = "updated";
}
Now the modified code above Console.WriteLine(content.ValueOne); will print out the word "updated".
In the below example, should I have used Func as I want a reference to
an the instantiated SomeContent object? If so can you provide an
example?
There's nothing being returned in this case so no you should not use Func. Func does not have any impact whatsoever on your desire to have reference type behavior.
I am a C++ programmer, now working on a C# project.
I am trying to understand in the below snippet why the value of string does not change even though the function is changing its value, I thought it is an object and would be passed as a reference.
public class TestClass
{
public TestClass(String passedStr)
{
passedStr = "Change me";
}
}
class Program
{
static void Main(string[] args)
{
String aString="I am what i am";
TestClass obj = new TestClass(aString);
Console.WriteLine(aString);
}
}
But behavior with user defined classes are different.
public class TestClass
{
private int x;
public int ID
{
get
{
return x;
}
set
{
x = value;
}
}
public TestClass(int a)
{
x = a;
}
}
public class Tester
{
public Tester(TestClass obj)
{
obj.ID = 999;
}
}
class Program
{
static void Main(string[] args)
{
TestClass obj = new TestClass(555);
Tester tester = new Tester(obj);
Console.WriteLine(obj.ID);
}
}
Let's go back to basics.
A variable is a storage location.
A variable of type string is a storage location that stores either null, or a reference to a string.
"passedStr" and "aString" are different variables.
When you call "new TestClass(aString)" you create a new storage location for "passedStr" and copy the contents of "aString" into it. You now have two variables that have the same content: a reference to a string.
Inside the constructor you change the value stored in the storage location for "passedStr". "aString" remains the same.
The "ref" and "out" keywords in C# mean "make the formal parameter and the argument aliases of each other". In that case you have only one variable with two different names. When you change one of them the other one changes as well, because they are the same variable.
No, it's passed by value; there's no ref keyword.
It's passing a reference type (here, a class) by value (no ref keyword), just like passing a copy of a pointer in C++. You're reassigning the pointer, not the actual data (which you can't do with strings anyway).
If you need pass-by-reference, try:
public TestClass(ref String passedStr)
{
passedStr = "Change me";
}
...
TestClass obj = new TestClass(ref aString);
Strings are passed by reference but the pointer is passed by value in C#. If you want to pass the string by reference you'll have to make use of the ref key word.
For example:
public class TestClass
{
public TestClass(ref string passedStr)
{
passedStr = "Change me";
}
}
class Program
{
static void Main(string[] args)
{
string aString="I am what i am";
TestClass obj = new TestClass(ref aString);
Console.WriteLine(aString); // "Change me"
}
}
passedStr is not the string, but a constructor parameter that holds a reference to the string. All your TestClass constructor is doing is changing the string that this parameter references. It has no effect outside the constructor.
What you are doing in the constructor, is that you are assigning a new String literal to the local variable passedStr.
In C, the equivalent function would look something like this:
Testclass constructor_testclass(char* passedStr) {
passedStr = "Change me";
}
I think it's obvious that this function does not change the value of the char* in the calling function.
The object I am what i am is being passed by reference, but the reassignment is to a local variable. You don't change the original object, but instead assign a new object (Change me) to the location of the argument.
public class Employee
{
public string ID { get; set; }
public string Name { get; set; }
public override string ToString()
{
return string.Format("ID = {0} Name = {1}", ID, Name);
}
}
public class TestClass2
{
public TestClass2(Employee e)
{
e.ID="007";
e.Name="james";
}
}
static void Main()
{
Employee e = new Employee();
e.ID = "0";
e.Name = "nobody";
TestClass2 t = new TestClass2(e);
Console.WriteLine(e); //Output ID = 007 Name = James
}
strings are passed by reference but the pointer is passed by value in C#
Parameter passing in C# by Jon Skeet