Variables from a specific class equality both sides still changing together if one of the sides change - c#

I am new to C# and WPF, and I am trying to define a new variable from a class and to give this new variable a value from an old variable and then make some changes to the new one. But the problem is that the new variable is still connected to the old variable and if I change anything in the new one, the changes will effect the old one:
MW.CurrentPreviewJob = addjob;
MW is another page than the page I am writing the code in,
and I define them as follows:
public static Job addjob;
public Job CurrentPreviewJob
{
get { return _currentPreviewJob; }
set {
_currentPreviewJob = value;
this.NotifyPropertyChanged("CurrentPreviewJob");
}
}
the class for the two variables is same and it is:
public partial class Job
{
public int JOB_ID { get; set; }
public string JOB_DESCRIPTION { get; set; }
public byte[] TARGET_IMAGE { get; set; }
public int JOB_USER { get; set; }
}
So how can I take the value of CurrentPreviewJob without stay connecting to it?

This is because an object of a class is a reference type.
Let's take a look at an example:
We create an object of your class:
Job someJob = new Job();
What exactly is someJob? Well, when you create an instance of an object it is held in special area of memory, and someJob holds a reference to it (which is an address under which the program can find the instance in the memory).
So when you do something like:
Job someOtherJob = someJob;
you actually tell someOtherJob object to hold reference to the same address in a memmory as someJob object. that's how reference types work.
Now, if you do, for example:
someOtherJob.JOB_DESCRIPTION = "I changed that description in some other job object";
This is what happens: program checks the address which is referenced by somOtherJob object, goes there, finds the instance, and change its JOB_DESCRIPTION property's value. BUT remember that someJob objct (the "old" one) has a reference to the same instance in the memory - hnce, it will have the same, changed JOB_DESCRIPTION.
The most elegant thing to do here is to implement some kind of cloning method on the Job class.
public partial class Job
{
public int JOB_ID { get; set; }
public string JOB_DESCRIPTION { get; set; }
public byte[] TARGET_IMAGE { get; set; }
public int JOB_USER { get; set; }
public Job Clone() {
Job clone = new Job();
clone.JOB_ID = this.JOB_ID;
clone.JOB_DESCRIPTION = this.JOB_DESCRIPTION;
clone.TARGET_IMAGE = this.TARGET_IMAGE;
clone.JOB_USER = this.JOB_USER;
return clone;
}
}
and use it like:
Job someOtherJob = someJob.Clone();

That happens because both CurrentPreviewJob and addjob are reference types. They both reference the same object in the memory. So whatever you do to one variable will also affect the other, since they are pointing to the same object. You can make your Job have a Clone method like this:
public partial class Job
{
public int JOB_ID { get; set; }
public string JOB_DESCRIPTION { get; set; }
public byte[] TARGET_IMAGE { get; set; }
public int JOB_USER { get; set; }
public Job Clone()
{
return new Job {
JOB_ID = this.JOB_ID,
JOB_DESCRIPTION = this.JOB_DESCRIPTION,
TARGET_IMAGE = this.TARGET_IMAGE,
JOB_USER = this.JOB_USER
};
}
}
Then you can assign your CurrentPreviewJob like this:
MW.CurrentPreviewJob = addjob.Clone();
This will make another object so your second variable is no longer linked to your previous.
Or another way is to make your class a struct

The problem is because Job is a class, and classes are reference types, meaning that if you assign one job variable to another, you just have too variables referencing the same data.
You could declare Job as a struct, which are value types and assignment would automatically create a copy.
I tend to avoid structs, simply because I don't like having to copy things around just to change properties, so I'd suggest adding an appropriate constructor to Job, like:
public Job(Job other) {
this.JOB_ID = other.JOB_ID;
this.JOB_DESCRIPTION = other.JOB_DESCRIPTION;
//...same for the other fields
}
Once you have the constructor, you can clone the object by doing:
var NewJob = new Job(OldJob);

Related

Issue while invoking a class and storing data into it c#

I have a class like this
public class basic
{
public bool Success { get; set; } = false;
public string Message { get; set; } = string.Empty;
}
public class ServiceResponse<T>:basic
{
public T? Data { get; set; }
}
public class ServiceResponse2<T> : basic
{
public T?[] Data { get; set; }
}
And I invoke it in my controller like this
ServiceResponse2<string> response = new ServiceResponse2<string>();
response.Success = true;
response.Message = "success";
response.Data[0] = filename;
response.Data[1] = outname;
when I do, I get runtime error in my lastline as: Object reference not set to an instance of an object. I hovered on top of Data variables and the values were null. Can I know what I'm missing here? Apologies if its a dumb doubt
The problem is that Data is an array, and this is never initialized to an object. You need to initialize it, for example:
response.Data = new string[]{filename, outname};
Or
public T?[] Data { get; set; } = new T[2];
However, I would be careful with using an array like this. What does Data means? How should it be used? Why can I change it however and whenever I want? How is it related to the other properties? Does a specific index have some special meaning? Does it promise to hold some specific number of items?
If this is intended to be used for requests to some type of service it is normal to use some form of serialization to convert objects to data. And this is normally done fairly close to the communication layer, so that most of the code can handle typed objects, and only a small part need to handle bits and bytes.

c# how to increment id for each instance of class automatically

A user inserts KID NAME, the code instantiate an object and add it to list of objects.
How to give each object a unique number automatically starting at 1, such that first KID(object) gets number 1, second KID gets number 2 etc.
I tried something like this but the result is "stackoverflow".
How would the class should be?
class Kid
{
public string KidName{ get; set; }
private static int Number { get; set; }
public int KidNumber { get; set; }
public Kid (string name)
{
this.KidName = name;
Number++;
this.KidNumber = Number;
}
}
Your code works successfully on my device.
Maybe you have an 'stackoverflow' for other reasons?
If you need only to identify Kid class, the alternative way is to use Guid:
class Kid
{
public string KidName { get; set; }
public Guid KidNumber { get; set; }
public Kid(string name)
{
this.KidName = name;
this.KidNumber = Guid.NewGuid();
}
}
Nothing in your example can induce a StackOverflowException. Stackoverflows occur when you repeatedly call the same method recursively either directly or indirectly (by way of an intermediate) or when you have an instance-level field of the same type as the instance itself (a special case of the former). You don't exhibit either case in your example so it must be due to something else external to the code you've shown. The most your code could potentially exhibit is an OverflowException if you were in a checked context.
That said, your approach is OK at first glance with the obvious pitfall that it is not thread-safe. Two instance could in theory end up with the same KidNumber. You can fix that by making use of the Interlocked class:
using System.Threading;
class Kid
{
private static int _counter;
public string KidName { get; set; }
public int KidNumber { get; set; }
public Kid(string name)
{
this.KidName = name;
this.KidNumber = Interlocked.Increment(ref _counter);
}
}
Like ++ in an unchecked context, this handles the case of overflow; once you hit int.MaxValue, if will automatically wrap to int.MinValue. If you don't want negative IDs you'll have to handle that seperately.

Writing out properties specific to a Derived Class

I need to determine which object my code is working with at a certain point and write out only the properties specific to that class. I cannot figure out how to do it. I was told I can do it, but I cannot figure it out. Can someone please show me how to determine which object I am working with and write the properties specific to that class only?
I've looked at other questions asked, but am not smart enough to make it fit my example.
Below, I've re-created an example of the code I am working with. I can see all the code, but I am allowed to only work in one method (for this example called "MethodIAmWorkingIn"). Only modifications I am allowed to make are in that method.
public class Program
{
static void Main(string[] args)
{
TestDetailsAndResultsContainer container = new TestDetailsAndResultsContainer();
DerivedClass1 derivedClass1 = new DerivedClass1();
derivedClass1.DerivedClass1Prop1 = "DerivedClass1Prop1";
derivedClass1.DerivedClass1Prop2 = "DerivedClass1Prop2";
DerivedClass2 derivedClass2 = new DerivedClass2();
derivedClass2.DerivedClass2Prop1 = "DerivedClass2Prop1";
derivedClass2.DerivedClass2Prop2 = "DerivedClass2Prop2";
container.TestDetails.Add(derivedClass1);
container.TestDetails.Add(derivedClass2);
TestResult testResult = new TestResult();
testResult.TestResultProp1 = "TestResultProp1";
testResult.TestResultProp2 = "TestResultProp2";
container.Data.Add(testResult);
Program p = new Program();
p.MethodIAmWorkingIn(container);
}
private void MethodIAmWorkingIn(TestDetailsAndResultsContainer container)
{
// I need to see if the container variable holds a DerivedClass1 or DerivedClass2 object.
foreach (var result in container.TestDetails)
{
var classINeedToDetermine = container.TestDetails.FirstOrDefault(m => m.TestDetailsProp1 == result.TestDetailsProp1);
if (classINeedToDetermine is DerivedClass1)
{
classINeedToDetermine = result as DerivedClass1;
}
else if (classINeedToDetermine is DerivedClass2)
{
classINeedToDetermine = result as DerivedClass2;
}
// Now I need to use the classINeedToDetermine object and write its specific properties.
// ???????????????????? I am stuck at this point ??????????????????
// I need to write one or the other below. Can this be done?
// If it is DerivedClass1, I need to write out those properties only.
Console.WriteLine(classINeedToDetermine.DerivedClass1Prop1);
Console.WriteLine(classINeedToDetermine.DerivedClass1Prop2);
// OR
// If it is DerivedClass2, I need to write out those properties only.
Console.WriteLine(classINeedToDetermine.DerivedClass2Prop1);
Console.WriteLine(classINeedToDetermine.DerivedClass2Prop2);
}
}
}
public class TestDetailsAndResultsContainer
{
public TestDetailsAndResultsContainer()
{
this.Data = new List<TestResult>();
this.TestDetails = new List<TestDetails>();
}
public List<TestDetails> TestDetails { get; set; }
public List<TestResult> Data { get; set; }
}
public abstract class TestDetails
{
public string TestDetailsProp1 { get; set; }
public string TestDetailsProp2 { get; set; }
}
public class TestResult
{
public string TestResultProp1 { get; set; }
public string TestResultProp2 { get; set; }
}
public class DerivedClass1 : TestDetails
{
public string DerivedClass1Prop1 { get; set; }
public string DerivedClass1Prop2 { get; set; }
}
public class DerivedClass2 : TestDetails
{
public string DerivedClass2Prop1 { get; set; }
public string DerivedClass2Prop2 { get; set; }
}
The as keyword does not do what you think it does.
Your classINeedToDetermine is a variable of type TestDetails. You can assign a subclass instance to it, but you still cannot access that subclasses specific properties via that variable.
You just need some scope:
if (classINeedToDetermine is DerivedClass1)
{
var derived1 = (DerivedClass1)result;
Console.WriteLine(derived1.DerivedClass1Prop1);
// etc
}
else if (classINeedToDetermine is DerivedClass2)
{
var derived2 = (DerivedClass2)result;
Console.WriteLine(derived2.DerivedClass2Prop1);
// etc
}
This kind of thing is not fun to maintain though.
Another way of doing it would be to use polymorphism: Your TestDetails class could define an abstract method called PrintProperties, and all your subclasses could implement it.
Then you just have to call PrintProperties on every object, without worrying about which subclass they are.
I'm not completely sure on what objects mean what here, but it should be something like this:
foreach(var v in result.GetType().GetProperties())
{
if(v.DeclaringType == result.GetType())
{
Console.WriteLine(v.GetValue(result));
}
}
Again, I wasn't totally clear on your usage of classINeedToDetermine versus result, but you can change those as you see so fit. I chose result as my example since classINeedToDetermine was null by that part of your code.
And by the way, this section of your code is redundant. It should be removed for clarity and efficiency.
if (classINeedToDetermine is DerivedClass1)
{
classINeedToDetermine = result as DerivedClass1;
}
else if (classINeedToDetermine is DerivedClass2)
{
classINeedToDetermine = result as DerivedClass2;
}
Edit:
On the other hand, if performance is more important to you than being scalable (read: if you know or have control over all the classes you'll be dealing with), you could use this is section to do something less, I hate to use this word for this, "generic."
if (classINeedToDetermine is DerivedClass1)
{
var typed = (DerivedClass1)result;
Console.WriteLine(typed.DerivedClass1Prop1);
Console.WriteLine(typed.DerivedClass1Prop2);
}
else if (classINeedToDetermine is DerivedClass2)
{
var typed = (DerivedClass2)result;
Console.WriteLine(typed.DerivedClass2Prop1);
Console.WriteLine(typed.DerivedClass2Prop2);
}
You can use Type.GetProperties to get all Properties for your class. Then you need to get the MethodInfo for the Get method via GetMethod.
Once you have the MethodInfo you can call Invoke, passing in your Derived Class. You can write then write the result to the Console.

Generic Lists in a HttpSessionState stored in SQL

I'm working on a aspx application (C#), where I'm using HttpSessionState to save different objects in code behind between view changes. Some of these objects containts generic lists (List<T>), but those lists doesn't seem to be saved when I'm using an SQL database to store the state (sessionState mode = "SQLServer"). All other properties in the object gets saved, but when I try to retrieve the list, I get empty lists.
The funny thing is that it all works fine if I use sessionState mode = "InProc".
My classes have the Serializable attribute. I'm running C#/.NET 4.0.
Any ideas would be appreciated!
EDIT:
Just to clarify with some code (not verbatim!).
I have the classes I want to save (instances of) to my Session State:
public class MyClass
{
public string Property1 { get; set; }
public string Property2 { get; set; }
public List<MyOtherClass> Property3 { get; set; }
}
public class MyOtherClass
{
public string AnotherProperty1 { get; set; }
public string AnotherProperty2 { get; set; }
}
Then, in my Code Behind - one action saves objects of the previous classes:
public void MyMethod()
{
MyClass myClass = new MyClass()
{
Property1 = "One string",
Property2 = "One other string",
Property3 = new List<MyOtherClass>() { new MyOtherClass() { AnotherProperty1 = "One", AnotherProperty2 = "Ohter" } }
};
HttpContext.Current.Session["MyKey"] = myClass;
}
...and another action will retrieve that object:
public void MyOtherMethod()
{
MyClass myClass = (MyClass)HttpContext.Current.Session["MyKey"];
int c = myClass.Property3.Count; // Will be 0!!
}
So myClass.Property1 and myClass.Property2 will hold the strings I set previously, but myClass.Property3 is an empty list.
The problem you are describing could happen if you
Store a reference to an object in that generic list that is valid when you store it, but
the reference is no longer valid on subsequent requests.
An example would be storing a reference to a control from the Page.Controls collection - this reference would not be valid if you try to retrieve it on another postback. In fact, the reference may just be cleaned up by garbage collection (thus why your list appears to be empty).
Without seeing your actual code, it's tough to say for sure (although your example code does a great job of clarifying what you mean). But this seems likely to me.

How do I get the value of the used parameters in a constructor (C#)

I've got a question about getting the values from a constructor in a generic way.
namespace myTestNamespace
{
Public Class myTestClass()
{
Public myTestClass(int myInt,bool myBool, double myDouble)
{
//do / set something
}
Public myTestClass(int myInt,bool myBool)
{
//do / set something
}
}
}
Using (what you need);
Using myTestNamespace;
namespace MyIWannaLookForTheParametersName
{
Public Class MyLookUpClass()
{
Public void DoSomething()
{
List<object> myList = new List<object>();
myTestClass _ myTestClass = new myTestClass(1,true,2.5);
object mySaveObject = myTestClass;
mylist.Add(mySaveObject);
//how do I get the info from the right constructor
//(I used the one with 3 parameters_
//what was the value of myInt, myBool and myDouble
//how can I make it generic enough, so it will work with other classes with
// different constructors ass well?
}
}
}
Questions about intent aside, there's no generic way for you to do this. Information about what methods have been called and what values were supplied is not saved automatically. You are, of course, perfectly able to keep track of these things yourself, but you would have to write each class to do this explicitly.
Doing this in a generic way is asking for trouble. What if I did this?
public class Foo
{
public string Name { get; set; }
}
public class Bar
{
public Bar(Foo foo)
{
// ...
}
}
Then suppose I called it in this way:
Foo f = new Foo();
f.Name = "Jim";
Bar b = new Bar(f);
f.Name = "Bob";
Now, if such a generic system existed, what would be the value of foo for the Bar constructor? Either it reports "Bob" (which is what the value for Name is on the instance of Foo that was supplied), or it reports "Jim", meaning that the runtime or library would essentially have to be smart enough to make a deep copy of the object so that the state is not changed.
The bottom line is this: if you need access to the parameters passed to the constructor (or any other function), you'll have to store them somewhere explicitly.
You can't get thevalues from the constructor. You need to first place them in a property or a field within your class. The example you provided is a poor use of generics. You wouldbe better off placing the constructor values into properties and creating an interface with those properties.
I got what I needed with this method:
private static ParameterSettings[] GetListOfParametersFromIndicator(object indicatorClass, int loopId, myEnums.ParaOrResult paraOrResult)
{
return (from prop in indicatorClass.GetType().GetProperties()
let loopID = loopId
let Indicator = indicatorClass.GetType().Name
let value = (object)prop.GetValue(indicatorClass, null)
where prop.Name.Contains("_Constr_")
select new ParameterSettings { ParaOrResult=paraOrResult, LoopID= loopId, Indicator= Indicator, ParaName= prop.Name, Value= value }).ToArray();
}
where ParameterSettings is:
public struct ParameterSettings
{
public myEnums.ParaOrResult ParaOrResult { get; set; }
public int LoopID { get; set; }
public string Indicator { get; set; }
public string ParaName { get; set; }
public object Value { get; set; }
}
This info is ok for me. Thanks for the replies.
Regards,
Matthijs

Categories

Resources