Constantly repeating class constructor - Class object seems to be instantiating itself - c#

I'm currently running into an issue where a class is seemingly creating an instance of itself or repeating its constructor causing an infinite loop.
I got a Singleton called Hotel. This currently holds a 2d array of Room (Room[,] HotelGridLayout) and a list of its guests/customers (Guests). It creates a Customer at the last line of the constructor in Hotel.
Customer Constructor:
public Customer(string _classPref, Room _entrance)
{
ClassificationPreference = _classPref; // Preference for classification (type of room)
FilePath = #"HotelPictures\Customer.png"; // String for image file path
CheckIn(_entrance);
}
CheckIn():
private void CheckIn(Room _entrance)
{
_entrance.UpdateForgroundImage(FilePath);
Room _roomAvailable = HotelForm.Instance.CheckInAtHotel(ClassificationPreference);
// some more stuff that doesn't even get reached.
}
important parts of Hotel constructor:
private HotelForm()
{
HotelGridLayout = JsonToHotelLayout.DeserializeHotelLayout(JsonString); // not the issue
Customers = new List<MovableObject>();
Cleaners = new List<MovableObject>();
MovableObject _testGuest = new Customer("5 stars", HotelGridLayout[1, 0]);
}
Here is the deal: After _entrance.UpdateForgroundImage(FilePath);, right before calling CheckInAtHotel(), it either creates a new Customer class or re-runs the constructor. It should not have anything to do with UpdateForgroundImage since this literately only assigns the Image displayed in a PictureBox (it's 1 line).
UpdateForgroundImage:
public virtual void UpdateForgroundImage(string _imageFilePath)
{
PictureBoxRoom.Image = Image.FromFile(Path.Combine("..", "..", "..", "..", _imageFilePath));
}
What is going on? Am I just blind and missing something completely obvious?
Source of issue:
I found the source of the issue: In Customer.CheckIn() I was getting the HotelForm instance via it's static property. Since that Customer was created in the constructor of HotelForm and requested the instance before it was set, it kept creating/updating instances of HotelForm; this code shows why:
public static HotelForm Instance
{
get
{
lock (_padlock)
{
if (_instance == null)
{
_instance = new HotelForm();
}
return _instance;
}
}
}
The instance didn't exist yet since the constructor wasn't finished (so to say), so it created a new instance of HotelForm, repeating the process thus constantly creating Customers.

Related

Values fetched from database and assigned to variables do not persist across layers

I have a class like this and the purpose is to set these Boolean values in the data layer with purpose of persisting these values in through out application's life cycle.
public class ProjectFeatureIndicatorMetadata
{
public bool? SprcCustomIncludesInd;
public bool? SprcCustomVariablesInd;
public bool? SprcRatingFlowInd;
public bool? SprcFactorSetsGenerationInd;
public static void SetFeatureIndicatorValues(string name, bool value)
{
ProjectFeatureIndicatorMetadata indicators = new Data.ProjectFeatureIndicatorMetadata();
if(name == "SprcCustomIncludesInd") { indicators.SprcCustomIncludesInd = value; }
if(name == "SprcCustomVariablesInd") { indicators.SprcCustomVariablesInd = value; }
if(name == "SprcRatingFlowInd") { indicators.SprcRatingFlowInd = value; }
if(name == "SprcFactorSetsGenerationInd") { indicators.SprcFactorSetsGenerationInd = value; }
}
}
Then I have the data layer, pretty straight forward. I can confirm that database call is made and values are being fetched and at this level, the indicators are assigned values:
public void GetCachedProjectFeatureIndicatorsStatus(ProjectIdentifier projectId)
{
ProjectFeatureIndicatorMetadata indicatorData = new ProjectFeatureIndicatorMetadata();
GetSpHelper().ExecuteReader(
spName: "ITV.usp_ProjectFeatureIndicators_GetByProjectId",
parmsDg: parms => parms.AddWithValue("#ProjectId", projectId.Guid),
methodDg: reader =>
{
while (reader.Read())
{
ProjectFeatureIndicatorMetadata.SetFeatureIndicatorValues(
"SprcCustomVariablesInd", reader.Column<bool>("SprcCustomVariablesInd"));
ProjectFeatureIndicatorMetadata.SetFeatureIndicatorValues(
"SprcRatingFlowInd", reader.Column<bool>("SprcRatingFlowInd"));
ProjectFeatureIndicatorMetadata.SetFeatureIndicatorValues(
"SprcFactorSetsGenerationInd", reader.Column<bool>("SprcFactorSetsGenerationInd"));
ProjectFeatureIndicatorMetadata.SetFeatureIndicatorValues(
"SprcCustomIncludesInd", reader.Column<bool>("SprcCustomIncludesInd"));
}
return true;
});
}
The application start up class calls middle layer through an interface. Below is hot it's implemented. The four 'vars' are just a test code but the bottom line is, values for the indicator variables are null. And I don't know why.
Data.GetCachedProjectFeatureIndicatorStatus(project);
ProjectFeatureIndicatorMetadata indicators = new ProjectFeatureIndicatorMetadata();
var sprcCustomIncludesInd = indicators.SprcCustomIncludesInd;
var sprcCustomVariablesInd = indicators.SprcCustomVariablesInd;
var sprcFactorSetsGenerationInd = indicators.SprcFactorSetsGenerationInd;
var sprcRatingFlowInd = indicators.SprcRatingFlowInd;
The Data object is class variable in the start up class:
private ProjectData Data
{
[Pure, DebuggerStepThrough]
get { return ProjectDataProvider.ProjectData; }
}
ProjectData is large class that holds lot of other stuff but my code only has this call to the interface:
public void GetCachedProjectFeatureIndicatorStatus(ProjectIdentifier projectId)
{
_server.GetCachedProjectFeatureIndicatorStatus(projectId);
}
Then another class that has the following method that is the main logic for this task:
public void GetCachedProjectFeatureIndicatorStatus(ProjectIdentifier projectId)
{
ProjectFeatureIndicatorMetadata indicators = new ProjectFeatureIndicatorMetadata();
using (new WriteLock(_lock))
{
if (indicators.SprcCustomIncludesInd != null ||
indicators.SprcCustomVariablesInd != null ||
indicators.SprcFactorSetsGenerationInd != null ||
indicators.SprcRatingFlowInd != null)
{
return;
}
else
{
GetProjectFeatureIndicatorsStatus(projectId);
return;
}
}
}
public virtual void GetProjectFeatureIndicatorsStatus(Guid projectId)
{
string PROJECT_SERVER_SQL_CONNECTION_STRING = ConfigurationManager.ConnectionStrings["ConfigConnectionString"].ConnectionString;
var configConnectionFactory = new ManualConnectionFactory(PROJECT_SERVER_SQL_CONNECTION_STRING);
var projectFeatureIndicatorTable = new ProjectFeatureIndicatorsTable(configConnectionFactory);
projectFeatureIndicatorTable.GetCachedProjectFeatureIndicatorsStatus(projectId);
}
I don't fully understand some of your code, like why in your method that has a DataReader, you make a new object instance of ProjectFeatureIndicatorMetaData but then you start looping the reader and make a bunch of static calls like:
while (reader.Read())
{
ProjectFeatureIndicatorMetadata.SetFeatureIndicatorValues(
"SprcCustomVariablesInd", reader.Column<bool>("SprcCustomVariablesInd"));
This won't do anything with the instance you just made, and you don't appear to access the static again outside the data reading loop, nor do you return the instance you made - you instead make another new instance in a different method and then try to access its properties (which will be null)
ProjectFeatureIndicatorMetadata indicators = new ProjectFeatureIndicatorMetadata();
using (new WriteLock(_lock))
{
if (indicators.SprcCustomIncludesInd != null ||
Ultimately if you want your data to travel round your app you have to make an instance, fill it with data and then pass it somewhere (call a method and pass it as a parameter/return it from a method to a method that captures the return value). Right now you have some static things, some non static things and whenever you want to do anything you make a new instance, fill it with data and then immediately throw it away, or you make a new instance and try to read from it as though you expect it to contain data. It's like you expect statics to be some sort of defaulting mechanism that, once called, mean that every new instance you make of that type gets the "defaults" that were set by calling the static methods - statics aren't like that. Statics are more like "there is one instance of the static stuff, that the runtime makes for you, but to access it you must always use it in a static way(no instance variables, just the type name)" - you're mixing "new" (==make a new instance) with static(==a single already existing instance the runtime made)
I'd generally advise to stay away from statics as a way of passing data around; as global variables they're almost always a bad idea in potentially concurrent situations. If you're setting up a cache of commonly used data at startup they may make sense but it introduces a high level of coupling to your classes; every class becomes dependent on the static and has to know what it is and cannot function without it. If you code in a more Dependency Injection style where you give every class instance the data it needs to function when you construct it, you don't get to a place where all classes depend on one - instead they use the data they're given and it isn't mandated how it gets it - you can use that class in a future project just by dropping it in and providing the same initial data from a different way

Replacing an object on so that all references to it are kept

I wanted to understand more about how the ref keyword works so I made the following experiment:
[TestClass]
public class UnitTest1
{
[TestMethod]
public void TestMethod1()
{
var main = new Main { Property = 1 };
var dependent = new Dependent(main);
void ChangeRef(ref Main Oldmain, Main newMain)
{
Oldmain = newMain;
}
ChangeRef(ref main, new Main { Property = 5 });
Assert.AreEqual(5,dependent.Main.Property);
}
}
public class Main
{
public int Property { get; set; }
}
public class Dependent
{
public Dependent(Main main)
{
Main = main;
}
public Main Main { get; set; }
}
As you can see I was expecting to be able to replace the object that main was referencing while keeping the reference, but the test fails and with the value still being 1. Could someone elaborate abit on why that wasnt working or point me to a place where I can read more?
Update:
Like someone answered below, but later removed.
Why doesnt it work if I pass the main object by reference to the dependent in the constructor?
Shouldnt they all have the same reference?
As others have pointed, you cannot instantly make all variables and fields in your program point to a different instance.
But if you want to reflect a change in all parts of the program, the simplest way is to wrap it in a different class (like your Dependent class). Then you can share the class with other parts of the program, and change its properties instead:
class SomeOtherObject
{
readonly Dependent _dependent;
public Dependent { get { return _dependent; }}
public SomeOtherObject(Dependent dependent)
{
_dependent = dependent;
}
public void Print()
{
Console.WriteLine(_dependent.Main.Property);
}
}
So now you can do this:
var dependent = new Dependent(new Main { Property = 1 });
var someOtherObject = new SomeOtherObject(dependent);
// this will print "1"
someOtherObject.Print();
dependent.Main = new Main { Property = 5; };
// this will print "5"
someOtherObject.Print();
In this case, obviously, simply changing dependent.Main.Property would also do the trick. So, if all parts of your program point to a single object, you can mutate it (i.e. change its internal data) and everyone will see the change, but you cannot make all parts of your program change what they are pointing to.
It's worth noting that you need to be careful when doing this in multithreaded programs; you rarely want some other thread to be able to randomly change your internal data.
That's also why it's best to try to keep your properties readonly, and your objects immutable, if possible.
After doing that
var main = new Main { Property = 1 };
You have object of type Main allocated somewhere in memory (let's name it Main1), at some memory address X, and variable main points to that object. "Points" means it literally stores address of that object Main1, so main contains X.
Then you pass reference to Main1 to the constructor of Dependent object
var dependent = new Dependent(main);
Dependent object is also allocated somewhere in memory, and one of its fields stores reference to Main1 object. So dependent.Main also stores X.
When you do
ChangeRef(ref main, new Main { Property = 5 });
You allocate new object Main5 somewhere at memory address Y. Now you change what address variable main points to. Before it stored address X (address of Main1), now it stores address Y (address of Main5). But dependent.Main still stores address X, because you didn't change it in any way, so it still points to object Main1.

c# doesn't work struct adding to list

I have
struct Park
{
...
}
and I need, to add 10 elements of this struct to List.
public List<Park> Parks = new List<Park>();
static void Main(string[] args)
{
new Program().CreatePark();
...
}
public void CreatePark()
{
for (int i = 1; i <= 10; i++)
{
Park temp = new Park();
temp.ID = i;
temp.Number = "abc";
temp.Property = false;
try
{
Parks.Add(temp);
}
catch (ArgumentException)
{
Console.WriteLine("oh no :(");
}
Console.WriteLine(temp.ToString());
}
}
And this doesn't work. Console.WriteLine(temp.ToString()); - this shows struct element, but when I want to print all elements, from Parks it's not working.
Parks.Count shows 0.
Given that you're using the statement: new Program().CreatePark(); the list of objects that you've created is not accessible after you create them. You have already thrown away the instance of the object holding the List. You have no way to access the list that you created to know what you had put in it.
The only thing the rest of your code could possibly do is create an entirely separate instance that has its own list, one that is entirely different from the one that you populated.
You'll need to hold onto the reference to the Program object if you want to inspect the list after you've populated it.
Parks is an instance variable.
CreateParks is an instance method.
Main is a static method, so you can't access the instance method or variable from it.
new Program() creates a new instance of the Program class.
Since the newly created program is not stored in a variable, it is discarded, and you can't access its Parks list after that.
To access the Parks list, you need to keep a reference to the instance of the program class like this:
Program program = new Program();
program .CreateParks();
foreach(Park park in program .Parks)
{
// Do something with the park
}
For anything more than a simple program, you will be better off having all the logic which isn't related to starting the program outside the Program class.
For example, you could create a new ParkManager class which is responsible for creating the parks and providing access to them.
Your program would look a bit like this:
public static class Program
{
static void main(string[] args)
{
ParkManager parkManager = new ParkManager();
parkManager.CreateParks();
foreach (Park park in parkManager.Parks)
{
// do something with park
}
}
}
public class ParkManager
{
// Setter is private to prevent other classes from replacing the list
// This doesn't prevent other classes from adding or removing,
// replacing or editing items in the list
public List<Park> Parks {get; private set;}
// Constructor - you could populate the list from here if appropriate
public void ParkManager()
{
Parks = new List<Park>();
}
public void CreateParks()
{
// Populate the list of parks here
}
}

C# Private member shared by all class instances

I am currently working with C# using the Unity3D engine and have come upon the following problem:
I created a class that has two private references to instances of another class which it has to access. Once I create multiple instances of the class and set the references I found out that all instances were using the same variable. I realized this as I was destroying an instance and just before that set the two variables holding the references to null. Immediately after doing that all other instances were throwing NullReferenceExceptions because they were still trying to access the references. The referenced objects are fine, other scripts can still access them.
Here is some pseudo code illustrating the structure:
public class Character
{
// Character data
}
public class StatusEffect
{
private Character target;
private Character originator;
public void Init(Character _Target, Character _Originator)
{
target = _Target;
originator = _Originator;
}
public void Destroy()
{
target = null;
originator = null;
}
}
In the program it would be called like this:
StatusEffect effect = new StatusEffect();
effect.Init(player1, player2);
// Time goes by
effect.Destroy();
After calling Destroy() every StatusEffect's two references will be null.
This is not only an issue when destroying StatusEffects, but also when creating new ones. As soon as I touch the references from within a new instance all StatusEffects will reference the two Characters specified by the new StatusEffect.
I do not understand why or how I can fix this issue. Can someone enlighten me on this matter?
Cheers,
Valtaroth
EDIT:
Here is the real code as requested:
I have a container class holding several StatusEffects. As soon as it starts, it initializes all of them.
public class CElementTag
{
// ..Other data..
public float f_Duration; // Set in the editor
private CGladiator gl_target;
private CGladiator gl_originator;
private float f_currentDuration;
public CStatusEffect[] ar_statusEffects;
// Starts the effect of the element tag
public void StartEffect(CGladiator _Originator, CGladiator _Target)
{
gl_originator = _Originator;
gl_target = _Target;
f_currentDuration = f_Duration;
for(int i = 0; i < ar_statusEffects.Length; i++)
ar_statusEffects[i].Initialize(gl_originator, gl_target);
}
// Ends the effect of the element tag
public void EndEffect()
{
for(int i = 0; i < ar_statusEffects.Length; i++)
{
if(ar_statusEffects[i] != null)
ar_statusEffects[i].Destroy();
}
}
// Called every update, returns true if the tag can be destroyed
public bool ActivateEffect()
{
f_currentDuration -= Time.deltaTime;
if(f_currentDuration <= 0.0f)
{
EndEffect();
return true;
}
for(int i = 0; i < ar_statusEffects.Length; i++)
{
if(ar_statusEffects[i] != null && ar_statusEffects[i].Update())
RemoveStatusEffect(i);
}
return false;
}
// Removes expired status effects
private void RemoveStatusEffect(int _Index)
{
// Call destroy method
ar_statusEffects[_Index].Destroy();
// Remove effect from array
for(int i = _Index; i < ar_statusEffects.Length - 1; i++)
ar_statusEffects[i] = ar_statusEffects[i+1];
ar_statusEffects[ar_statusEffects.Length - 1] = null;
}
}
The actual StatusEffect class is holding the two references as well as some other data it needs to work. It has virtual methods because there are some classes inheriting from it.
public class CStatusEffect
{
// ..Necessary data..
// References
protected CGladiator gl_target;
protected CGladiator gl_originator;
virtual public void Initialize(CGladiator _Target, CGladiator _Originator)
{
gl_target = _Target;
gl_originator = _Originator;
// ..Initialize other necessary stuff..
}
virtual public void Destroy()
{
gl_target = null;
gl_originator = null;
// ..Tidy up other data..
}
virtual public bool Update()
{
// ..Modifying data of gl_target and gl_originator..
// Returns true as soon as the effect is supposed to end.
}
}
That should be all the relevant code concerning this problem.
EDIT2
#KeithPayne I have a static array of ElementTags defined in the editor and saved to xml. At the beginning of the program the static array is loading the xml and stores all element tags. When creating a new element tag to use I utilize this constructor:
// Receives a static tag as parameter
public CElementTag(CElementTag _Tag)
{
i_ID = _Tag.i_ID;
str_Name = _Tag.str_Name;
enum_Type = _Tag.enum_Type;
f_Duration = _Tag.f_Duration;
ar_statusEffects = new CStatusEffect[_Tag.ar_statusEffects.Length];
Array.Copy(_Tag.ar_statusEffects, ar_statusEffects, _Tag.ar_statusEffects.Length);
}
Do I have to use a different method to copy the array to the new tag? I thought Array.Copy would make a deep copy of the source array and stored it in the destination array. If it is in fact making a shallow copy, I understand where the problem is coming from now.
From Array.Copy Method (Array, Array, Int32):
If sourceArray and destinationArray are both reference-type arrays or
are both arrays of type Object, a shallow copy is performed. A shallow
copy of an Array is a new Array containing references to the same
elements as the original Array. The elements themselves or anything
referenced by the elements are not copied. In contrast, a deep copy of
an Array copies the elements and everything directly or indirectly
referenced by the elements.
Consider this fluent version of the StatusEffect class and its usage below:
public class StatusEffect
{
public Character Target { get; private set; }
public Character Originator { get; private set; }
public StatusEffect Init(Character target, Character originator)
{
Target = target.Clone()
Originator = originator.Clone();
return this;
}
//...
}
public CElementTag(CElementTag _Tag)
{
i_ID = _Tag.i_ID;
str_Name = _Tag.str_Name;
enum_Type = _Tag.enum_Type;
f_Duration = _Tag.f_Duration;
ar_statusEffects = _Tag.ar_statusEffects.Select(eff =>
new StatusEffect().Init(eff.Target, eff.Originator)).ToArray();
// ar_statusEffects = new CStatusEffect[_Tag.ar_statusEffects.Length];
// Array.Copy(_Tag.ar_statusEffects, ar_statusEffects, _Tag.ar_statusEffects.Length);
}
Because you're passing in references to the objects via your Init() method, you're not actually "copying" the objects, just maintaining a reference to the same underlying objects in memory.
If you have multiple players with the same references to the same underlying objects, then changes made by player 1 will effect the objects being used by player 2.
Having said all that, you're not actually disposing the objects in your Destory method. Just setting the local instance references to Null which shouldn't affect any other instances of StatusEffects. Are you sure something else isn't disposing the objects, or that you haven't properly init'd your other instances.
If you do want to take a full copy of the passed in objects, take a look at the ICloneable interface. It looks like you want to pass in a copy of the objects into each Player.
public class Character : ICloneable
{
// Character data
//Implement Clone Method
}
public class StatusEffect
{
private Character target;
private Character originator;
public void Init(Character _Target, Character _Originator)
{
target = _Target.Clone()
originator = _Originator.Clone();
}
The fields aren't shared(static) among other instances. So calling target = null; in Destroy() won't affect other instances.
StatusEffect effect1 = new StatusEffect();
effect1.Init(player1, player2);
StatusEffect effect2 = new StatusEffect();
effect2.Init(player1, player2);
// Time goes by
effect2.Destroy();
// Some more time goes by
// accessing effect1.target won't give a `NullReferenceException` here unless player1 was null before passed to the init.
effect1.Destroy();
I think you did forget the Init(..) on the other instances. Every time you create an instance of StatusEffect, you need to call Init(...).
Update:
This line will clear the reference to the effect, but you never recreate it:
ar_statusEffects[ar_statusEffects.Length - 1] = null;
so the next time you call ar_statusEffects[x].Update() or Initialize() etc it will throw a NullReferenceException
If you want to clear out effects within you array, you could create an Enable bool in the effect, this way you only have to set/reset it.
for(int i = 0; i < ar_statusEffects.Length; i++)
if(ar_statusEffects[i].IsEnabled)
ar_statusEffects[i].Update();
Why don't you use a List instead? Arrays will be faster as long you don't have to shuffle in it. (like circulair buffers etc)
Thanks to Keith Payne I figured out where the problem was. I was creating a deep copy of CElementTag, but not of my ar_statusEffects array. I wrongly assumed Array.Copy was creating a deep copy of an array when it actually was not.
I implemented the IClonable interface for my CStatusEffect and use the Clone() method to create a true deep copy for each member of the static array and add it to the new tags ar_statusEffects array. This way I have seperate instances of the effects instead of references to the same static effect.
Thanks to everyone, especially Keith Payne, for their help and support!

Passing variables from Main function to another C# class

I'm beating my head against the wall pretty severely with this. I have several variables inside a C# console application that I would like to re-use. However, I cannot for the life of me re-use the variables in another class. I would love any help or pointers you could provide - I've searched for quite some time and I'm completely stumped.
EDIT: Yes, the variables are inside my Main function. Sorry for leaving this out.
EDIT: Heavily redacted code below. The variable values I'd like to re-use in another class are in the middle. There are more but those 3 should be sufficient for the sample. Thanks for the assistance!!!
public static class MyApp
{
static void Main(string[] args)
{
// loads XML doc
foreach (XmlNode node in nodes)
{
try
{
// does a bunch of stuff
// Parses variables from REST API
XDocument docdetailxml = XDocument.Parse(xmldoc);
XNamespace ns = docdetailxml.Root.GetDefaultNamespace();
var buid = docdetailxml.Root.Element(ns + "busid").Value;
var bname = docdetailxml.Root.Element(ns + "busname").Value;
var bcount = docdetailxml.Root.Element(ns + "buscount").Value;
// Invoke SQL connection string
// Trigger Stored Procedure and write values to database
// If needed, trigger email notification
// Close connections
}
catch (Exception e)
{
Console.WriteLine("Error encountered: " + e.Message);
// Exit the application
System.Environment.Exit(1);
}
finally
{
// Exit the application
// System.Environment.Exit(0);
}
}
}
private static void GetConnectionString()
{
throw new NotImplementedException();
}
private static void GetConnectionStrings()
{
throw new NotImplementedException();
}
}
}
you should define public property or public field
public class Student
{
public string Name {get;set;}
}
and when you want to pass value you can assign this value to property
Student st = new Student();
st.Name = "your value";
or you can use class constructor too.
If the variable denote some information about an object (like name, id, etc.) then they should be encapsulated in a class. The instance of the class (called an object) should be used to access this information.
As you already have the variables that represent an object, the next step would be to group these variables into classes. These variables are represented as properties in the class. The operations performed on these members should be available as methods. Furthermore the access modifiers decide the visibility of the members.
Going through your example, I can identify 3 variables that represent a Customer (assumption, I am not sure of the exact use case). These will form the Customer class.
class Customer
{
// You can either pass the UID through the constructor or
// expose a public setter to allow modification of the property
public Customer(string uid)
{
this.UID = uid;
}
public string UID { get; private set; }
public string Name { get; set; }
public string Count { get; set; }
}
Furthermore, the foreach loop can be split into 2 parts for resuablity
Read from the xml nodes and create a list of customers
Perform the database operations (like trigger stored procedures, write values, etc.) on the list of customers
Additionally, you can create another class that does the operations (business logic) that you are performing in the console application. This will allow you to reuse the same logic in case you move it to another application (like winforms or web service).
More information
Object oriented programming
Object oriented concepts in C#
Principles Of Object Oriented Design
I think there's a dedicated forum for struts on this site, best look there for more info.
Quick answer: the primary way of passing values from one action to another (I think you are working with struts Action classes?) is to put the values into the request or session (so, first job for you would be to read up on those topics: HttpServletRequest and HttpSession). Struts action classes do their work in the execute() method, and that method has a parameter of type HttpServletRequest. From the request you can get a handle to the session.
And both request and session offer methods getAttribute() and setAttribute(). So, to pass data from one action to another, set that data as a (request or session) attribute, then read out the attribute in the next action again.
The Program class is probably Static so you'll have to access those fields by class name instead of instance.
class Program
{
public string Name = "a name";
static void Main(string[] args)
{
Name = "Hello"; //You can't do this, compile error
Program p = new Program();
p.Name = "Hi"; //You can do this
SecondName = "Sn"; //You can do this
Program.SecondName = "Tr"; //You can do this too
}
public static string SecondName = "Peat";
}

Categories