|
|
Thanks to anybody who feels like helping the beginner.
I want to create a system wherein objects are accessing each other and I struggle to understand reference passing. For example, I wish I could write a function that specifically targets one instance of a class, but I only see how to write functions that take object references as arguments such that I have to call the function with the correct reference each time. I show the way I tried, right in the middle of my code below with all the ????. How do I aim functions at specific objects, given that I only get to write function definitions when defining a class, and the other class's objects don't even exist yet? And, in my code, do I correctly comment the things which do seem to work as intended?
Also, there seems to be nothing in the books about this. Doesn't this trip up everybody when they first try to access one object from another? There's stuff about the Observer pattern and deligates and ref modifiers and values versus references, but nothing directly about this basic point. Is there a name or keyword for this topic or for a discussion of this?
By the way, I understand having objects talk directly can tangle things and is a mixed blessing. I still want to grasp the idea.
I'm using:
Programming C# (Liberty)
The C# Programming Language (Hejlsberg...)
C# In a Nutshell (Drayton...)
C# Essentials (Albahari...)
Murach's C# (Murach)
Visual C# 2005 Demystified (Kent)
The Object-Oriented Thought Process (Weisfeld)
as well as several C++ books like Eckel and Prata and the MSDN and CodeProject forums.
Thanks!!
using System;
// Here is an exercise between objects, that studies reference passing.
// The Main function instantiates User, Counter and Reporter objects and
// calls on some of their members. Since the objects are in scope in Program,
// no passing of references is needed. However, when Main asks a Reporter's
// method to call members of User and Counter objects, Main must pass
// Reporter references to the User and Counter objects. But the Reporter
// needs no reference to reach method in static FunctionHolder class.
// ???? I wanted to define a method that specifically accesses Counter2
// ???? instance of Counter but don't see how to do so! See line 95.
namespace ClassesAndObjects
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Initialize all.");
// Construct 3 Users, 2 Counters and a Reporter
Reporter ConcreteReporter = new Reporter();
User User1 = new User();
User User2 = new User();
User User3 = new User();
Counter Counter1 = new Counter();
Counter Counter2 = new Counter();
// Try a bunch of things, reporting various properties each time
// This function call needs object references but no static class ref:
ConcreteReporter.Report(User1, User2, User3, Counter1, Counter2);
Console.WriteLine("Do User1.Make6()");
// User1.Make6() is in scope, no reference passing required
User1.Make6();
ConcreteReporter.Report(User1, User2, User3, Counter1, Counter2);
Console.WriteLine("Do User1.X = 9");
User1.X = 9;
ConcreteReporter.Report(User1, User2, User3, Counter1, Counter2);
Console.WriteLine("Do Counter1.Increment()");
Counter1.Increment();
ConcreteReporter.Report(User1, User2, User3, Counter1, Counter2);
Console.WriteLine("Do User1.X = Counter1.I");
User1.X = Counter1.I;
ConcreteReporter.Report(User1, User2, User3, Counter1, Counter2);
Console.WriteLine("Do Counter2.Increment() Twice");
Counter2.Increment();
Counter2.Increment();
ConcreteReporter.Report(User1, User2, User3, Counter1, Counter2);
Console.WriteLine("Do User2.XGetsI(Counter2)");
// Must pass reference, which tells User2 which Counter to call.
User2.XGetsI(Counter2);
ConcreteReporter.Report(User1, User2, User3, Counter1, Counter2);
Console.WriteLine("Do User2.X = Counter2.I");
User2.X = Counter2.I;
ConcreteReporter.Report(User1, User2, User3, Counter1, Counter2);
Console.WriteLine("Do Counter2.Increment()");
Counter2.Increment();
ConcreteReporter.Report(User1, User2, User3, Counter1, Counter2);
Console.WriteLine("Do User3.XGetsIFromCounter2(Counter1), it uses Counter1");
// Must pass reference, which (unfortunately) is what chooses the counter
User3.XGetsIFromCounter2(Counter1);
Console.WriteLine("Look, did not read Counter2 as intended:");
ConcreteReporter.Report(User1, User2, User3, Counter1, Counter2);
Console.WriteLine("Do User3.XGetsIFromCounter2(Counter2), it uses Counter2");
// This time, pass reference to the counter that was intended all along
User3.XGetsIFromCounter2(Counter2);
Console.WriteLine("Look, it read Counter2, just because of the reference:");
ConcreteReporter.Report(User1, User2, User3, Counter1, Counter2);
// Keep console window open for examination.
Console.ReadLine();
}
}
public class User
// Objects of this class can directly use a property in objects of Counter class
// and have members the Reporter and Program objects can directly call
{
private int x;
public User()
{
x = 5;
}
public void Make6()
{
x = 6;
}
// NOTE this function needs a reference to the Counter object
public void XGetsI(Counter CounterN)
{
// Expression uses the reference I passed in as argument
X = CounterN.I;
}
// ????????????????????????????????????????????????????????????
// How could I define a function that specifically targets Counter2?
// Lines below just use "Counter2" as a local identifier
// the same way "CounterN" is used a few lines above so this code
// does NOT specify Counter2, which wouldn't exist here anyway.
// ???????????????????????????????????????????????????????????
public void XGetsIFromCounter2(Counter Counter2)
{
X = Counter2.I; // Unfortunately this doesn't mean my Counter2 object!
}
public int X
{
set
{
x = value;
}
get
{
return x;
}
} // end property X
} // end class User
public class Counter
// Objects of this class have a property and a function which
// User, Reporter and Program objects will directly call
{
private int i;
public Counter()
{
i = 0;
}
public int I
{
get
{
return i;
}
}
public void Increment()
{
i = i + 1;
}
} // end class Counter
public class Reporter
// Function in an object of this class will directly call members of User and Counter objects
// and of the static class FunctionHolder. This function requires User and Counter object
// references as arguments because those objects are only instantiated in another class at
// runtime and do not yet exist during the definition of this class. But it does not need
// to be passed a reference to the static class FunctionHolder because that doesn't wait
// for a runtime instantiation.
{
public Reporter()
{
// No data members to initialize
// Could put singleton construction in here
}
public void Report(User User1, User User2, User User3, Counter Counter1, Counter Counter2)
{
Console.WriteLine("U1.X={0}, U2.X={1}, U3.X={2}, C1.I={3}, C2.I={4}, Fifty={5}\n", User1.X, User2.X, User3.X, Counter1.I, Counter2.I, FunctionHolder.Fifty());
} // end class Reporter
}
public static class FunctionHolder
// This class is static and others use its method with just ClassName.MethodName().
{
public static int Fifty()
{
return 50;
}
} // end class FunctionHolder
} // end namespace ClassesAndObjects
|
|
|
|
|
You're doing good, it's apparent you're picking up some things pretty well.
I see your problem. You're thinking, "how can I write a function that just works on some particular object instance (e.g. Counter2)"?
The problem is, that's not the way functions work supposed to work. Functions in C# are either instance functions (they work on the current instance) or static (they work on any instance you pass them). For example, say you want a SayHello() method on your Counter object. You can code it up to work on all Foo objects:
class Counter
{
public string MyName;
public void SayHello()
{
Console.WriteLine(MyName);
}
}
Now you can go like this:
Counter counter1 = new Counter();
counter1.MyName = "I am the first counter!";
Counter counter2 = new Counter();
counter2.MyName = "I am the second counter!";
counter1.SayHello();
counter2.SayHello();
See what happened? The SayHello method worked on the current instance.
Static methods don't belong to any instance; therefore they have to be passed the instance to work on:
class Counter
{
public static void StaticSayHelloMethod(Counter instanceToUse)
{
Console.WriteLine(instanceToUse.MyName);
}
}
Now if you want to use that, you have to pass the instance in:
StaticSayHelloMethod(counter1);
StaticSayHelloMethod(counter2);
Does that answer your question?
p.s. next time use <pre> tags around your code (e.g. <pre> code goes here </pre> ) when you post it on the forums. This way, formatting will be preserved, your code will be easier to read on the forums, and the likelihood of someone answering your question increases.
|
|
|
|
|
Judah, yes, thanks, that's it perfectly. I guess this means there'd be a frequent pattern where a sort of a "switchboard" or "coordinator" object manages the calls of other objects on each other? Maybe there's also a way for objects of the same class that are in an array or collection together to know how to call, say, their North or West neighbor, like if you're iterating on a finite element mesh or convolving pixel values throughout an image (or maybe the "coordinator" object just foreach's through the array calling methods with (i,j) and (i+1,j) indices).
And thanks for the
tip, I'll use it!
|
|
|
|
|
I need to run an executable program from a C# program and I need to run the program of a a number of times and I have to save the output each time. I tried something but it saves my only the last output. How can I do it?
|
|
|
|
|
You can use System.Diagnostics.Process class to run external programs. You can use Process.StandardOutput to get the output of each process.
|
|
|
|
|
If you use the process class you can execute your application. If you tie into the standard output you can receive that output and do stuff with it. I have an example of this in this article I wrote:
http://www.codeproject.com/dotnet/OpenFiles.asp[^]
Hope that helps.
Ben
|
|
|
|
|
sounds like a bug in your code. Care to show code ?
|
|
|
|
|
I am already using Process class to run the executable program. The output files are created by the arguments given to the executable program. I tried to give a different name to the output each time. I am runing the program with the help of a cycle. And the input changes name in each cycle and the output the same. But the only thing it's saved it is the last output. How can I solve this?
|
|
|
|
|
You can try this a simple solution.
For the output take a fixed name say "simpleoutput".
Now when you run your executable it should create a file name using the above fixed name and the courrent name i.e.
outputFileName = "simpleoutput" + <currentdatetime> value. So you will get the unique file name.
Your executable should write in these files.
Manoj
Never Gives up
|
|
|
|
|
Anka_Ame wrote: saves my only the last output
Are you, by chance, creating the file each time and not appending to the file? Creating the file each time you save would seem like it only saves the last value. If you want all of the values in the same file, you need to append the values in the file.
Why is common sense not common?
Never argue with an idiot. They will drag you down to their level where they are an expert.
Sometimes it takes a lot of work to be lazy
|
|
|
|
|
Hello,
I have a FlowLayoutPanel that I populate with my user controls. I have approximatelly 20 controls in the flowpanel.
If I select a specific control programatically, and then scroll to it programatically using the statement:
this.flowPanel.ScrollControlIntoView (myControl)
However, the scrolling will stop the moment control is fully visible, and that makes control appear on the right side of the flowpanel.
What I want to do, is for the flowpanel to scroll enough for the myControl to line up with the left edge of the flow panel. Is there a way about it, like setting certain properties?
Thank you very much.
|
|
|
|
|
Could you temporarily set the width of myControl to flowPanel.Width, call ScrollControlIntoView, then reset the width of myControl back to normal?
|
|
|
|
|
Thank you
It works, the problem, you notice a bit of blinking withing the control. I guess it's due to myControl changing size.
|
|
|
|
|
hi
i want to ignore some characters in serach within strings, for example, when user typed 'water' and click search,at the result, plus 'water', some words like 'wâter' or 'wãter' also find.
thanks
|
|
|
|
|
Regex regex = new Regex("w(a|â|ã)ter");
bool regularAMatches = regex.IsMatch("water");
bool funnyAMatches = regex.IsMatch("wãter");
bool iMatches = regex.IsMatch("witer");
|
|
|
|
|
I am having a small problem whle inserting my data into a database through a stored procedure in sql.
The table schema is as follow: C_Name, C_Capital,C_Currency,C_President
The problem is that when enter data through a stored procedure only the first lettter of each value is stored in each column.
e.g(if i enter "Australia","Canberra","Dollar","John Howard")only (A,C,D,J)
get stored in their respective columns why is this happening can anybody help me out.
The Code is given below:
SqlCommand cmd= new SqlCommand("sp_insert",conn);
cmd.CommandType=CommandType.StoredProcedure;
cmd.Parameters.Add(new SqlParameter("@cname",SqlDbType.NChar,50,"C_Name"));
cmd.Parameters.Add(new SqlParameter("@ccapital",SqlDbType.NChar,50,"C_Capital"));
cmd.Parameters.Add(new SqlParameter("@ccurrency",SqlDbType.NChar,50,"C_Currency"));
cmd.Parameters.Add(new SqlParameter("@cpresident",SqlDbType.NChar,50,"C_President"));
cmd.Parameters[0].Value="Australia";
cmd.Parameters[1].Value="Canberra";
cmd.Parameters[2].Value="Australian Dollar";
cmd.Parameters[3].Value="John Howard";
int i=cmd.ExecuteNonQuery();
Console.WriteLine(i);
The Code of the stored procedure is:
create procedure sp_insert @cname nchar,@ccapital nchar,@ccurrency nchar
,@cpresident nchar
as insert into country values(@cname,@ccapital,@ccurrency,@cpresident)
plz..help.It's Urgent....
|
|
|
|
|
In the country table, what are the datatypes for cname, ccapital, and ccurrency? Are they nchar(1)?
|
|
|
|
|
No they are not nchar(1), its nvarchar(50)....can u figure out a solution to this
|
|
|
|
|
Try:
create procedure sp_insert @cname nchar(50),@ccapital nchar(50),@ccurrency nchar(50),@cpresident nchar(50)
Read this:nchar and nvarchar (Transact-SQL) [^]
Regarding nchar [ ( n ) ] it states when n is not specified in a data definition or variable declaration statement, the default length is 1.
topcoderjax - Remember, Google is your friend.
|
|
|
|
|
Thanx a lot it worked.....now how can i create a procedure that returns a row how can i read it in .net
|
|
|
|
|
I want to serialize program settings to a binary file. The problem is that the settings are written to a binary file but I cannot retrieve them into a propertygrid control. Here is the code.
<code>
namespace OpsTest
{
[Serializable()]
public class ProgramSettings
{
private Font _editorFont;
private Color _editorTextColor;
[Category("Editor Settings"),
Description("The font used by the editor.")]
public Font EditorFont
{
get { return _editorFont; }
set { _editorFont = value; }
}
[Category("Editor Settings"),
Description("The text color used by the editor.")]
public Color EditorTextColor
{
get { return _editorTextColor; }
set { _editorTextColor = value; }
}
}
}
public partial class OptionsDialog : Form
{
ProgramSettings mySettings = new ProgramSettings();
public OptionsDialog()
{
InitializeComponent();
}
private void OptionsDialog_Load(object sender, EventArgs e)
{
optionsPropertyGrid.SelectedObject = mySettings;
SerializeLoad();
}
public void SerializeLoad()
{
string sFilename = Path.GetDirectoryName(Application.ExecutablePath) + @"\settings.dat";
if (File.Exists(sFilename))
{
Stream inStream = File.Open(sFilename, FileMode.Open);
BinaryFormatter bf = new BinaryFormatter();
mySettings = (ProgramSettings)bf.Deserialize(inStream);
inStream.Close();
}
}
public void SerializeStore()
{
string sFilename = Path.GetDirectoryName(Application.ExecutablePath) + @"\settings.dat";
Stream outStream = File.Open(sFilename, FileMode.Create);
BinaryFormatter bf = new BinaryFormatter();
bf.Serialize(outStream, mySettings);
outStream.Close();
}
private void okButton_Click(object sender, EventArgs e)
{
SerializeStore();
this.Close();
}
</code> The categories are there but no values appear in the propertygrid!
Thanks,
Mark
-- modified at 9:50 Friday 25th May, 2007
|
|
|
|
|
hi
change the two lines in the OptionsDialog_Load event.
you must load/deserialize the object and then set it to the propertygrid
selectedobject property.
regards
|
|
|
|
|
Hi,
There are two mistakes I can see:
1) You should set the 'mySettings" to "optionsPropertyGrid.SelectedObject" after loading. So the codeshould be :
SerializeLoad();
optionsPropertyGrid.SelectedObject = mySettings;
2) In function "SerializeStore" you should first copy the value of "optionsPropertyGrid.SelectedObject" to "mySettings" before serializing it.
That means you should add the below line in the function "SerializeStore".
mySettings = (ProgramSettings)optionsPropertyGrid.SelectedObject
Manoj
Never Gives up
|
|
|
|
|
|