Okay,
Maybe this is by design of c# or maybe I am going about this the wrong way.
Please look at the code I have below. I made it where you can copy and paste it into a console app and run it to see what I am talking about.
using System;
namespace ConsoleTest
{
class Program
{
static void Main()
{
var o1 = new oObject
{
Name = "Before Method"
};
var o1b = new oObjectBad
{
Name = "Before Method"
};
Console.WriteLine("Object Bad 1 Before: " + o1b.Name);
oObjectBad o2b = GetNewObjectBad(o1b);
Console.WriteLine("Object Bad 1 After: " + o1b.Name);
Console.WriteLine("Object Bad 2 After: " + o2b.Name);
Console.WriteLine(string.Empty);
Console.WriteLine("Object 1 Before: " + o1.Name);
oObject o2 = GetNewObject(o1);
Console.WriteLine("Object 1 After: " + o1.Name);
Console.WriteLine("Object 2 After: " + o2.Name);
Console.ReadLine();
}
public static oObject GetNewObject(oObject o)
{
oObject newObject = new oObject(o);
newObject.Name = "Changed in Method";
return newObject;
}
public static oObjectBad GetNewObjectBad(oObjectBad o)
{
o.Name = "Changed in Method";
return o;
}
}
class oObject
{
public oObject()
{
}
public oObject(oObject o)
{
Name = o.Name;
}
public string Name { get; set; }
}
class oObjectBad
{
public string Name { get; set; }
}
}
Now, here is what I don't understand.
When I pass in an object to the method, and update the objects property "Name". It then updates the original object which is outside of the method.
The way around this was to create the other object (as shown in code) to make a clone of the object and then update the clone and then return the clone.
So the question is this:
Is there an easier way to pass in an object and update the properties of that object so i can have something like this without it updating the original object.
using System;
namespace ConsoleTest
{
class Program
{
static void Main()
{
var o1 = new oObject
{
Name = "Before Method"
};
Console.WriteLine("Object 1 Before: " + o1.Name);
oObject o2 = GetNewObjectBad(o1);
Console.WriteLine("Object 1 After: " + o1.Name);
Console.WriteLine("Object 2 (New Object) After: " + o2.Name);
Console.ReadLine();
}
public static oObject GetNewObjectBad(oObject o)
{
o.Name = "Changed in Method";
return o;
}
}
class oObject
{
public string Name { get; set; }
}
}
If this is confusing let me know and I will see if I can explain better.
EDIT:
The reason why I am doing this is I need to clone an object in the database and the cloned object will need to have a couple of properties changed. I will then be using the ID from the original object and the new object for other data processing.
Thanks!
I would spend some time researching pass by reference vs. pass by value and then look at why you need to change the name in the local context but not in the original. I have the suspicion you might have some design flaws. I would revisit the problem and see if you can develop a solution with a different approach.
In .NET all objects are reference types unless they descend from ValueType. Typically you would not want to modify instance variables of an object directly anyway. You have much more control if you make instance variables private and then add methods to manipulate the private data.
http://msdn.microsoft.com/en-us/library/s1ax56ch.aspx List of decedents of ValueType.
Why would you want to change the object in a method and not have that data reflected in the calling method? One thing you could do is implement code to track changes, and give the class a method returning the original object with the original data.
Like others have said, this is a value type vs. reference type issue. If you really want to have the object not get changed, you can change your type to a struct. I'm not saying that is the answer though, I don't know your class structure to make an informed opinion on the matter.
Related
Very, very new programmer here facing some big troubles, I am trying to achieve as follows:
I want to write a very basic program in which the user is prompted to input two double variables, I then want the program to call separate methods, that will perform mathematical operations on those two variables and provide the user the answers.
Example of desired output:
Input First Number
x
Input Second Number
y
Add: z
Subtract: z
My aim in this is to practice using objects, but I am having issues, see this snippet as an example.
class Variables
{
public string First { get; set; }
public string Second { get; set; }
}
class Program
{
Variables inputs = new Variables()
{
Console.WriteLine("Please input first number"),
First = Console.ReadLine(),
Console.WriteLine("Please input second number"),
Second = Console.ReadLine(),
};
static void Main(string[] args)
{
Addthem();
}
public string Addthem()
{
double answer = Convert.ToDouble(inputs.First) + Convert.ToDouble(inputs.Second);
return ("Added: " + answer);
}
}
When trying to call Addthem, I have no 'object reference',
in my object 'inputs', I cannot print to console to prompt user input?
And finally (most mind bogglingly to me), my Main method is not suitable as an entry point for the program, this is what I am MOST clueless on.
Am I even on the right track? As I said very novice so sorry for egregious errors or general ignorance, I am just trying to better understand what I am not seeing in the interactions between Classes, Objects, Methods.
You've got all the ingredients right, but they need to be rearranged to make a good cake. Main() is the entry point, so anything you want to do has to be inside Main() or be called by something inside Main().
A useful concept to know is the difference between a class and an object.
A class is just a specification which says you can have these properties and methods, but you need to create an instance of the class first.
An object is an "instance" of a class and you can call the class methods (functions) through that object. Eg inputs is an instance of the Variables class.
using System;
class Variables
{
public string First { get; set; }
public string Second { get; set; }
public string AddthemInClass()
{
double answer = Convert.ToDouble(First) + Convert.ToDouble(Second);
return ("Added: " + answer);
}
}
class Program
{
static void Main(string[] args)
{
// You had the code to initialise `inputs` outside of Main(),
// so it wouldn't get executed
// It needs to be inside Main()
// `inputs` is created as an instance of the `Variables` class
Variables inputs = new Variables();
Console.WriteLine("Please input first number");
inputs.First = Console.ReadLine();
Console.WriteLine("Please input second number");
inputs.Second = Console.ReadLine();
// You need to tell Addthem() what to work on, ie, pass in `inputs`
var result = Addthem(inputs);
Console.WriteLine( result );
// Or, you could call AddthemInClass through the `inputs` object
// because AddthemInClass is a method of Variables class
var result2 = inputs.AddthemInClass();
Console.WriteLine( result2 );
}
// This should be a static method. If you don't do this, you need to have it
// in a class and call it through an instance of that class
// You could put it inside Variables class - see AddThemInClass()
public static string Addthem(Variables inputs)
{
double answer = Convert.ToDouble(inputs.First) + Convert.ToDouble(inputs.Second);
return ("Added: " + answer);
}
}
Consider the code below:
class Data
{
public string Name;
public string NameWithSufix;
}
class Behaviour
{
private Data data;
public string Name { get { return data.Name; } private set { } }
public Behaviour()
{
data = new Data()
{
Name = "My Name",
NameWithSufix = Name + " Sufix",
};
//data = new Data();
//data.Name = "My Name";
//data.NameWithSufix = Name + " Sufix";
}
}
class Program
{
static void Main(string[] args)
{
Behaviour behaviour = new Behaviour();
}
}
If you run this program, it will fail with NullReferenceException at Name property. This and this answer and Visual Studio try to persuade me object initializer and object constructors followed by property assignment are the same but it doesn't seem so. If I swap the body of constructor with commented code, it works. It seem like initiliazer doesn't actually run the constructor before it tries to assign properties. Why?
Name in NameWithSufix = Name points to data.Name, from which data is null at the time. A better representation for what object initializers do is this:
Data d = new Data();
d.Name = "My Name";
d.NameWithSufix = this.data.Name /*Name*/ + " Sufix"; // <-- see the problem here
this.data = d;
See that this.data isn't set until the object initializer is done.
This is supported by the C# language specification, as noted by PetSerAl.
It's running the Behavior constructor first. The problem is that the initialization of the Data class is not yet complete, so the following reference throws an exception
NameWithSufix = Name + " Sufix",
Because it calls get { return data.Name; } but data is still null at this point.
Update:
Patrick Hofman states it better and more accurately in his answer - it's not that the initialization of the Data class isn't complete, but that the new instance has not been assigned to the data variable yet.
Also, he requested a clarification to the official docs - give it a thumbs up if you agree.
This question already has answers here:
How to initialize a struct in C# [duplicate]
(4 answers)
C# Structs: Unassigned local variable?
(2 answers)
Initialization of instance fields vs. local variables
(7 answers)
Closed 5 years ago.
Please help anyone. This is my first question on this site.
I am a very beginner in C#, learning a little bit about C# structures. Here I have two source codes in C# with structures.
The first one is about a structure having record of two books such as Book Name, Author Name, Page No and Book ID. Here, in line 17, I declared two types of Book to access the members of the structures but not used the "new" operator. However, it compiled succesfully and gave the correct output.
Source Code 1 :
using System;
namespace StructureTest
{
struct Book
{
public string name;
public string author;
public int page_no;
public int book_id;
}
class Program
{
static void Main(String[] args)
{
Book Book1, Book2;
Book1.name = "Programming in ANSI C";
Book1.author = "E Balagurusamy";
Book1.page_no = 450;
Book1.book_id = 34567821;
Book2.name = "C Programming";
Book2.author = "Tamim Shahriar Subeen";
Book2.page_no = 280;
Book2.book_id = 34567477;
Console.WriteLine("Book1 Name = {0}", Book1.name);
Console.WriteLine("Book1 Author Name = {0}", Book1.author);
Console.WriteLine("Book1 Total Page No = {0}", Book1.page_no);
Console.WriteLine("Book1 ID = {0}", Book1.book_id);
Console.WriteLine("Book2 Name = {0}", Book2.name);
Console.WriteLine("Book2 Author Name = {0}", Book2.author);
Console.WriteLine("Book2 Total Page No = {0}", Book2.page_no);
Console.WriteLine("Book2 ID = {0}", Book2.book_id);
Console.ReadKey();
}
}
}
But in the second code, I differently declared two functions in that structure and use them to take the values of the records and print those as output. But surprisingly, the code didn't compiled showing these error messege,
prog.cs(39,13): error CS0165: Use of unassigned local variable `book1'
prog.cs(43,13): error CS0165: Use of unassigned local variable `book2'
Source Code 2 :
using System;
namespace StructureWithMethods
{
struct StructureMethods
{
public string name;
public string author;
public int page;
public int id;
public void setvalue(string a, string b, int c, int d)
{
name = a;
author = b;
page = c;
id = d;
}
public void printinfo()
{
Console.WriteLine("Name : " + name);
Console.WriteLine("Author : " + author);
Console.WriteLine("Total Page No : " + page);
Console.WriteLine("ID : " + id);
}
}
class Program
{
static void Main(String[] args)
{
StructureMethods book1,book2;
book1.setvalue("Aaj Himur Biye", "Humayun Ahmed", 232, 45771256);
Console.WriteLine("1st Book Record :");
book1.printinfo();
book2.setvalue("Raju O Agunalir Bhoot", "Md. Zafar Iqbal", 198, 45777129);
Console.WriteLine("\n2nd Book Record :");
book2.printinfo();
Console.ReadKey();
}
}
}
But, however after sometime I managed to use "new" keyword when declaring the type of struct Book and then it compiled succesfully and gave the correct output.
Now, my question is, Should I use "new" in structures while declaring methods only? Or is it mandatory to use "new" in structures while creating an object? But my first code compiled succesfully.
Should I use "new" in structures
Here is some useful information from MSDN:
When you create a struct object using the new operator, it gets created and the appropriate constructor is called. Unlike classes, structs can be instantiated without using the new operator. In such a case, there is no constructor call, which makes the allocation more efficient. However, the fields will remain unassigned and the object cannot be used until all of the fields are initialized.
So your first code compiled without error because you assigned all the fields and then you used the object.
The second code fails because the struct object cannot be used since you have not used the new operator or assigned all the fields yet, so you cannot use the object yet and call methods on it.
For example, in the code below new operator is not used but it works because all the fields have been initialized:
class Program
{
static void Main(string[] args)
{
A a;
a.X = 1;
a.Print();
Console.Read();
}
}
struct A
{
public int X;
public void Print()
{
Console.WriteLine("A has X: {0}", this.X);
}
}
However, the code below will not work because the fields have not been initialized:
class Program
{
static void Main(string[] args)
{
A a;
//a.X = 1; <------ SEE this is commented out
a.Print();
Console.Read();
}
}
struct A
{
public int X;
public void Print()
{
Console.WriteLine("A has X: {0}", this.X);
}
}
So in conclusion, you must either:
Initialize all the fields and then you can use the object
Use the new operator to invoke the constructor and then use the object.
Please note this only applies to structs and not classes. For classes, you can only use the static members without the new operator and to use the object of a class, you will have to use the new operator.
Although you don't need the new to instantiate a structure, the compiler will not let you use any method or property unless all of its fields are initialized.
You can either create a constructor instead of the setvalue method, or assign it one after the other:
StructureMethods book1;
book1.author = "ds";
book1.name = "";
book1.page = 1;
book1.id = 3;
book1.printinfo();
StructureMethods book2 = new StructureMethods("test","bbb",0,1);
book2.printinfo();
struct StructureMethods
{
public string name;
public string author;
public int page;
public int id;
public StructureMethods(string a, string b, int c, int d)
{
name = a;
author = b;
page = c;
id = d;
}
public void printinfo()
{
Console.WriteLine("Name : " + name);
Console.WriteLine("Author : " + author);
Console.WriteLine("Total Page No : " + page);
Console.WriteLine("ID : " + id);
}
}
Side-Note1: there is no need to use return; at the end of the function unless you are returning some value in a non-void method.
Side-Note2: Since you mentioned you are new to C#, be sure you understand when to use structs and when classes. You can start here
Well recently i came up with an idea (that i really don't know whether it would exist or even work) of automatic updating class's properties using an modified instance of it. And to make my idea a little bit more clear, i will explain it in the code below.
//The first (Main) instance of the class
Employee carl = new Employee();
carl.Name = "Carl";
carl.Age = 20;
carl.Salary = 7000;
//Here is the same employee data collected from the database a year after...
Employee carl_one_year_later = new Employee();
carl_one_year_later.Age = 21;
carl_one_year_later.Salary = 10000;
//Here comes the idea... I wanna dynamically merge the new collected data to the current main instance of the employee, without missing out the unupdated data ex : his name
employee1 = employee2; //using this seems to overwrite the Name Field with null...
Someone might say you can simply achieve this by doing this:
carl.Age = carl_one_year_later.Age;
carl.Salary = carl_one_year_later.Salary;
However, i want a dynamic way to just do this in 1 line of code and let C# handle the property set for me, also it may come in handy if we have a massive class that we don't want to set it's properties every time it is updated one by one.
NB: I hope i succeed in providing a clear image of my idea, and if you find any problem understanding what exactly do i need, just let me know.
using System;
using System.Reflection;
public class Test
{
public class Employee
{
public String Name{get;set;}
public int Age{get;set;}
public int Salary{get;set;}
}
public static void Main()
{
Employee e1 = new Employee{Name="Old", Age=20, Salary=1000};
Employee e2 = new Employee{Age=30, Salary=5000};
Copy(e2, e1);
Console.WriteLine(e1.Name+" "+ e1.Age+" "+e1.Salary );
}
public static void Copy<T>(T from, T to)
{
Type t = typeof (T);
PropertyInfo[] props = t.GetProperties(BindingFlags.Public | BindingFlags.Instance);
foreach (PropertyInfo p in props) {
if (!p.CanRead || !p.CanWrite) continue;
object val = p.GetGetMethod().Invoke(from, null);
object defaultVal = p.PropertyType.IsValueType ? Activator.CreateInstance(p.PropertyType) : null;
if (null != defaultVal && !val.Equals(defaultVal)) {
p.GetSetMethod().Invoke(to, new[] {val});
}
}
}
}
You can make a CopyTo extension method, like so:
public static class ObjectExtensions
{
public static void CopyTo<T>(this T fromObj, T toObj)
{
foreach(var p in typeof(T).GetProperties())
{
p.SetValue(toObj, p.GetValue(fromObj, null), null);
}
}
}
And call it like:
carl_one_year_later.CopyTo(carl);
Although, to be honest, there's a few more checks that should be made, and you'd be better off using something like AutoMapper instead.
Checkout ICloneable OR MemberwiseClone (unless you need to do a deep copy. Then check out a object mapper like Automapper, ValueInjecter or write your own custom object serialization hydrater)
http://msdn.microsoft.com/en-us/library/system.object.memberwiseclone.aspx
The MemberwiseClone method creates a shallow copy by creating a new object, and then copying the nonstatic fields of the current object to the new object.
http://msdn.microsoft.com/en-us/library/system.icloneable.aspx
Alternatives to AutoMapper
public static class ObjectExtensions
{
public static void CopyTo<T>(this T fromObj, T toObj)
{
foreach (var p in typeof(T).GetProperties())
{
if(p.GetValue(fromObj) == null)
{
continue;
}
p.SetValue(toObj, p.GetValue(fromObj, null), null);
}
}
}
Same as the above answer but just added "if" in "foreach" to skip the null values
The idea itself seems odd to me..
I, myself, would just rather do :
//The first (Main) instance of the class
Employee carl = new Employee();
carl.Name = "Carl";
carl.Age = 20;
carl.Salary = 7000;
//Here we get Carl from the database
Employee carl = GetFromDatabase("Carl") //Illustration
carl.Age = 21;
carl.Salary = 10000;
Your code is like saying nowadays Carl and next year Carl is a completely different person, and coincidentally having all those same attributes.
Although if it really needs to be done, I do tend to prefer Automapper..
This is my first time posting on Stack Overflow, so hopefully I did everything right and you guys can help.
I'm wondering if in C# there's a way to access a static variable belonging to a class, when given only the type of the class. For example:
public class Foo
{
public static int bar = 0;
}
public class Main
{
public void myFunc(Type givenType)
{
int tempInt = ??? // Get the value of the variable "bar" from "Foo"
Debug.WriteLine("Bar is currently :" + tempInt);
}
}
// I didn't run this code through a compiler, but its simple enough
// that hopefully you should get the idea...
It's hard to describe the context of needing to know this, but I'm making a game in XNA and I'm trying to use reference counting to reduce the complexity of the design. I have objects in the game and power-ups that can apply an effect them (that stays on the objects). Power-ups can die but their effects can still linger on the objects, and I need to keep track of if any effects from a power-up are still lingering on objects (thus, reference counting). I plan to make a "PowerUpEffect" class (for each type of power-up) with a static integer saving the number of objects still affected by it, but the design of the rest of the game doesn't work well with passing the PowerUpEffect all the way down to the object for it to call a method of the PowerUpEffect class.
I'm hoping to pass only the PowerUpEffect's type (using something like "typeOf()") and use that type to reference static variables belonging to those types, but I have no idea how to do it or if it's even possible.
I'd be glad to even find work-arounds that don't answer this questions directly but solve the problem in a simple and elegant design. =)
Help! (and thanks!)
If you only have the Type handle, you can do this:
var prop = givenType.GetProperty("bar");
var value = prop.GetValue(null);
I would use a Dictionary instead, which are probably the most concise way of mapping one set of values to another. If you are associating int values with Types, then do something like:
public static readonly Dictionary<Type, int> sTypeValues =
new Dictionary<Type, int>
{
{ typeof(Type1), 5 },
{ typeof(Type2), 10 },
{ typeof(Type3), 2 },
{ typeof(Type4), 3 },
{ typeof(Type5), -7 }
};
your function then becomes:
public void myFunc(Type givenType)
{
int tempInt = sTypeValues[givenType];
Debug.WriteLine("Bar is currently :" + tempInt);
}
int tempInt = (int) givenType.GetField("bar").GetValue(null);
Okay, so you have a collection of powerups, and you want to have an integer associated with each of those powerups. Rather than having a lot of classes, each with a static integer, you can have a single static collection which holds onto all of the powerups and their associated integer values.
public static class MyPowerupInfo
{
public static Dictionary<PowerUp, int> PowerUps {get; private set;}
static MyPowerupInfo
{
PowerUps = new Dictionary<PowerUp, int>();
PowerUps.Add(*some power up object goes here*, 0);
//TODO add other power ups
}
}
Then to use it you can do something like:
int powerupCount = MyPowerupInfo.PowerUps[wickedAwesomePowerup];
or:
public static void IncrementPowerup(Powerup powerup)
{
MyPowerupInfo.PowerUps[powerup] = MyPowerupInfo.PowerUps[powerup]+1;
}
If am getting you correc, this might give you some idea:
using System;
using System.Reflection;
public class RStatic
{
private static int SomeNumber {get; set;}
public static object SomeReference {get; set;}
static RStatic()
{
SomeReference = new object();
Console.WriteLine(SomeReference.GetHashCode());
}
}
public class Program
{
public static void Main()
{
var rs = new RStatic();
var pi = rs.GetType().GetProperty("SomeReference", BindingFlags.Static | BindingFlags.Public); // i have used GetProperty in my case
Console.WriteLine(pi.GetValue(rs, null).GetHashCode());
}
}
Are you assuming if the name of the field you're trying to access (for example, for the class "foo", the field "bar") is a different field based on the Type parameter?
If the name of the field is known based on a finite number of allowable types, you should be able to determine it with a switch statement. For example:
public class Foo
{
public static int bar = 0;
}
public class Baz
{
public static int bing = 0;
}
public class Main
{
public void myFunc(Type givenType)
{
switch (givenType.ToString())
{
case "Foo":
Debug.WriteLine("Bar is currently :" + Foo.bar);
break;
case "Baz":
Debug.WriteLine("Bing is currently :" + Baz.bing);
break;
}
}
}