Hey! I've made a little boiler system that's controlled entirely by a form. The form components, however, call functions in a class for the boiler, radiators and so on.
I've got a little main class to that instantiates all of the classes but I'm struggling to figure out how to pass the form object to those classes so that they can access the form's components.
I guess I should be using mutator methods in each class to store the form object? How would I do this that's syntactically correct?
Thank you! ;o)
Just pass the form to each class. Store it in a private variable so the class can use it later. It is passed by reference by default.
class Boiler {
private Form parentForm;
public Boiler(Form f) {
parentForm = f;
}
}
When you pass a reference type to a method, C# (by default) will pass a copy of the reference to the method. This means that if pass the reference you have to your classes you are giving the method a copy of that reference and since both copies reference the same object both the call site and the method will have access to the same instance.
For example:
class Example
{
static void Main()
{
string s = "hello, world";
// Here we are passing a copy of the reference
// stored in "s" to "Print"
Print(s);
}
static void Print(string str)
{
// By default, "str" will be assigned the copy of the
// reference passed to this method.
Console.WriteLine(s);
}
}
I would be careful building an application in which your domain objects (in your case, Boiler, Radiator, etc.) know about the UI layer that consumes them. If you find that you need to pass a Form to one of these domain models you are probably doing something wrong. If you show us a small example of what you are trying to accomplish we might be able to help you come up with a more maintainable solution.
Related
I made a program that works just fine as-is, however i want to organize code better by moving some of my logic into other .cs files; upon moving some code i noticed that code reffering the "this" keyword for changing the applications width / height no longer function and ive had no luck trying to get a handle to "this", please help
int heightd = (int)this.Height;
Edit: To further clarify. My mainwindow.xaml.cs is where all my code was before.
I would use this.width to get my windows width.
Upon creating a different .cs file to hold related methods, it broke all of my "this" refferences.
I want for my NEW cs file to be able to get a handle on "this" from my main program. so i can call its width, height, etc
Re-edit: I understand that "this" is not going to function properly from my new class I just want to be able to create methods that use the same object that is accessed when "this" is refferenced.
So for example, Class2 can do WorkAround.height ; where WorkAround is a handle to whatever "this" is in class 1.
Soution: updated signature in new class to accept the main window:
public static void Marginnn(MainWindow aplication)
{
send "this" from main class during the call:
WindowsInterop.Marginnn(this);
Others have discussed partial classes, which can be problematic. For this answer, I assume by "move to another .cs file" you mean "move to another class," as your title indicates.
The this keyword is effectively a variable that refers to the instance that "owns" the current method. If the method is moved to another type, then the instance can no longer be the owner of the method. Instead, you need to pass a reference to the instance into the method instead. That will be a method parameter, which will have a name other than this.
Example; before:
class App
{
public void DoSomethingWithTheHeight()
{
int heightd = (int)this.Height;
//more code
}
public void CallDoSomethingWithTheHeight()
{
this.DoSomethingWithTheHeight();
}
}
Task: move DoSomethingWithTheHeight to a new static class:
class App
{
public void CallDoSomethingWithTheHeight()
{
NewClass.DoSomethingWithTheHeight(this);
}
}
static class NewClass
{
public static void DoSomethingWithTheHeight(App application)
{
int heightd = (int)application.Height;
//more code
}
}
Task: move DoSomethingWithTheHeight to a new non-static class:
class App
{
public void CallDoSomethingWithTheHeight()
{
NewClass instanceOfNewClass = new NewClass();
instanceOfNewClass.DoSomethingWithTheHeight(this);
}
}
class NewClass
{
public void DoSomethingWithTheHeight(App application)
{
int heightd = (int)application.Height;
//more code
}
}
There are other possibilities, but these examples should illustrate the basic principle.
If you only want to move part of your class to another file and still use this, you have to use a partial class. But I won't recommend this approach, your code clearly needs some refactoring.
C# keyword this refers to the current instance of the class it's being used in. It can be used for a few other things such as a modifier of the first parameter of an extension method, but we won't worry about that here. So, you may only use this from within the class that it's referring to and note that it may not be used with static classes, methods, fields, etc... since they have no instance associated with them.
If the code you're referring to is not implemented within a partial class, then it has to refer to the instance of the Window. Otherwise, it's impossible to tell what this is. Since we don't know how exactly you're structuring your program, it's hard to recommend a method of fetching the instance of the Window in question. If, for example, you would use the MVVM pattern, you wouldn't even need to interact with the instance of the UI from within the code. However, if you're working with a code-behind model, then your best bet is probably to create a partial class for that window. Like I said, it's hard to know what's right in your situation without knowing the entire scope of your environment.
There are lots of ways to tackle this and some are more hackish than others:
// In the code-behind of a window...
public static MyWindow Instance { get; private set; }
public MyWindow()
{
Initialize();
Instance = this;
}
// Somewhere else in your program...
var someValue = MyWindow.Instance.SomeControl.Value;
Note that the above code is just for demonstration purposes and not something I would recommend doing (it doesn't even account for null, but that's easy to fix). It's simply a demonstration showing that there are almost countless ways of tackling your problem. Ideally, if you're not going with MVVM, I would probably implement a window manager class that handles instances of all of your application windows.
I want change the text of a label on one form to the text of a button on another form when I press the button.
To do this I have created this on the form where the label is
public static void changeText(string text)
{
L1.text = text;
}
this code is on the form with the button
mainForm.changeText(this.Text);
It then gives the error : An object reference is required for the non-static field, method, or property...
This may seem like a stupid question but I am still new to C# so please help me.
About static and non-static members
There are two kinds of type members: non-static and static. Non-static members are also called instance members, because they appear in the object instances of the type. Static members are bound to the type itself, and not its object instances, so you can use them without actually instantiating the type.
Consider the following:
class MyClass
{
// static member: can NOT reference 'this', as it is not in the context of an object instance of the type
public static bool IsTrue()
{
return true;
}
// constructor: this runs whenever the type is instantiated
public MyClass()
{
}
// instance member: can access to 'this', which references the context object instance of the type
public int GetNumber()
{
return 42;
}
}
You can use the above type as following:
if(MyClass.IsTrue()) // static call
{
var myObject = new MyClass(); // constructor call
int result = myObject.GetNumber(); // instance member call
Console.WriteLine(result);
}
On to your specific problem...
If you're perfectly sure that you need that logic inside a static method, you'll need to get an object instance of the form you wish to change.
Unfortunately singletons don't work very well, because the VS designer needs to create an object instance of your Form, which obviously violates the singleton pattern.
What you can still use, is (in case of a Windows Forms application): Application.OpenForms. This returns a read-only collection that contains all currently open forms of the application. You can use this to find the object instance of the form you want to change, and then perform that change.
Be advised that if this is a multi-threaded situation (i.e. the static method runs in a different thread than the GUI thread), you'll have to use some sort of synchronization mechanism, such as InvokeRequired and Invoke().
L1 is not static, so you cant have a static function interacting with it. Having a static let you able to write something like MainForm.changeText(...), but in this case what is L1 ?
I think we can say:
You dont need a function to change the label text, the property Text is already written
If there is some logic needed to mangle the tet before you can:
Consider if the function you need is so general that can apply to many labels across your app, in this case an extension method would be good. In other case if you want a function in the main form to set the text somewhere, and this place can change, or the text need some mangling, a member function would be good, and probably a DataBinding would be better.
You don't want to use a static method for this since L1 is a member of the mainForm class.
The error means your static function is accessing a non-static variable (control L1).
Static functions can only access to static variables. You can change L1 to static variable to make it work.
I know the title sounds a bit strange, but this has been boggling my mind for a little bit. So Intel offers this TurboBoost sidebar gadget with calls using JavaScript, and I want to write a program from scratch in C# that does the same thing. The calls stem from what I believe is an ActiveX DLL which I easily imported. The problem is, whenever I try to call a function, it gives me the error "an object reference is required for the non-static field..." I've found all of the functions e.g. the one I used return a dynamic data structure. I've tried splitting up the functions and made them both static but still no luck. Here's the code(ITurboBoostClient is the interface portion):
namespace TurboBoostMon_CLI
{
class Program
{
public static object GetCPUFreq()
{
object n = ITurboBoostClient.GetCurBaseFrequency(); //<---- error
//return Convert.ToDouble(n);
return n;
}
public static void Main(string[] args)
{
object cpubasefreq = GetCPUFreq();
Console.WriteLine(cpubasefreq); // neglect the output for now
}
}
}
If typical naming conventions are being used, ITurboBoostClient is an interface, and you do not have an instance of an object that implements the interface. Hence, the error.
Without knowing more about the ActiveX DLL, its hard to say exactly what to do, but it would be along the lines of:
{
ITurboBoostClient myClient = TurboBoostFactory.GetInstance();
object n = myClient.GetCurBaseFrequencey();
return n;
}
Note that in the first line, you call a static method that can product the class (with the interface) that is required. Then you can actually use that interface.
Look again through the ActiveX library you imported, and see if you can find a factory method, a CreateInstance method, or some other instantiator that will create the initial object.
If you're getting that error, then you need to declare something as a new object. Assuming your error marker is correct, you need to change that to create a new instance of some object that inherits the ITurboBoostClient, then use that to call the GetCurBaseFrequenct() method.
Something like:
ITurboBoostClient myTurboBoost = new TurboBoostClientObject(); // Making names up here, not familiar with the framework you're working with.
object n = myTurboBoost.GetCurBaseFrequency();
Sorry I don't know what class you need to instantiate there, but a short dig on google will most surely be revealing.
I want some variables to be global across the project and accessible in every form. How can I do this?
yes you can by using static class.
like this:
static class Global
{
private static string _globalVar = "";
public static string GlobalVar
{
get { return _globalVar; }
set { _globalVar = value; }
}
}
and for using any where you can write:
GlobalClass.GlobalVar = "any string value"
The consensus here is to put the global variables in a static class as static members. When you create a new Windows Forms application, it usually comes with a Program class (Program.cs), which is a static class and serves as the main entry point of the application. It lives for the the whole lifetime of the app, so I think it is best to put the global variables there instead of creating a new one.
static class Program
{
public static string globalString = "This is a global string.";
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1());
}
}
And use it as such:
public partial class Form1 : Form
{
public Form1()
{
Program.globalString = "Accessible in Form1.";
InitializeComponent();
}
}
Or you could put your globals in the app.config
You can use static class or Singleton pattern.
One way,
Solution Explorer > Your Project > Properties > Settings.Settings. Click on this file and add define your settings from the IDE.
Access them by
Properties.Settings.Default.MySetting = "hello world";
public static class MyGlobals
{
public static string Global1 = "Hello";
public static string Global2 = "World";
}
public class Foo
{
private void Method1()
{
string example = MyGlobals.Global1;
//etc
}
}
If you're using Visual C#, all you need to do is add a class in Program.cs inheriting Form and change all the inherited class from Form to your class in every Form*.cs.
//Program.cs
public class Forms : Form
{
//Declare your global valuables here.
}
//Form1.cs
public partial class Form1 : Forms //Change from Form to Forms
{
//...
}
Of course, there might be a way to extending the class Form without modifying it. If that's the case, all you need to do is extending it! Since all the forms are inheriting it by default, so all the valuables declared in it will become global automatically! Good luck!!!
They have already answered how to use a global variable.
I will tell you why the use of global variables is a bad idea as a result of this question carried out in stackoverflow in Spanish.
Explicit translation of the text in Spanish:
Impact of the change
The problem with global variables is that they create hidden dependencies. When it comes to large applications, you yourself do not know / remember / you are clear about the objects you have and their relationships.
So, you can not have a clear notion of how many objects your global variable is using. And if you want to change something of the global variable, for example, the meaning of each of its possible values, or its type? How many classes or compilation units will that change affect? If the amount is small, it may be worth making the change. If the impact will be great, it may be worth looking for another solution.
But what is the impact? Because a global variable can be used anywhere in the code, it can be very difficult to measure it.
In addition, always try to have a variable with the shortest possible life time, so that the amount of code that makes use of that variable is the minimum possible, and thus better understand its purpose, and who modifies it.
A global variable lasts for the duration of the program, and therefore, anyone can use the variable, either to read it, or even worse, to change its value, making it more difficult to know what value the variable will have at any given program point. .
Order of destruction
Another problem is the order of destruction. Variables are always destroyed in reverse order of their creation, whether they are local or global / static variables (an exception is the primitive types, int,enums, etc., which are never destroyed if they are global / static until they end the program).
The problem is that it is difficult to know the order of construction of the global (or static) variables. In principle, it is indeterminate.
If all your global / static variables are in a single compilation unit (that is, you only have a .cpp), then the order of construction is the same as the writing one (that is, variables defined before, are built before).
But if you have more than one .cpp each with its own global / static variables, the global construction order is indeterminate. Of course, the order in each compilation unit (each .cpp) in particular, is respected: if the global variableA is defined before B,A will be built before B, but It is possible that between A andB variables of other .cpp are initialized. For example, if you have three units with the following global / static variables:
Image1
In the executable it could be created in this order (or in any other order as long as the relative order is respected within each .cpp):
Image2
Why is this important? Because if there are relations between different static global objects, for example, that some use others in their destructors, perhaps, in the destructor of a global variable, you use another global object from another compilation unit that turns out to be already destroyed ( have been built later).
Hidden dependencies and * test cases *
I tried to find the source that I will use in this example, but I can not find it (anyway, it was to exemplify the use of singletons, although the example is applicable to global and static variables). Hidden dependencies also create new problems related to controlling the behavior of an object, if it depends on the state of a global variable.
Imagine you have a payment system, and you want to test it to see how it works, since you need to make changes, and the code is from another person (or yours, but from a few years ago). You open a new main, and you call the corresponding function of your global object that provides a bank payment service with a card, and it turns out that you enter your data and they charge you. How, in a simple test, have I used a production version? How can I do a simple payment test?
After asking other co-workers, it turns out that you have to "mark true", a global bool that indicates whether we are in test mode or not, before beginning the collection process. Your object that provides the payment service depends on another object that provides the mode of payment, and that dependency occurs in an invisible way for the programmer.
In other words, the global variables (or singletones), make it impossible to pass to "test mode", since global variables can not be replaced by "testing" instances (unless you modify the code where said code is created or defined). global variable, but we assume that the tests are done without modifying the mother code).
Solution
This is solved by means of what is called * dependency injection *, which consists in passing as a parameter all the dependencies that an object needs in its constructor or in the corresponding method. In this way, the programmer ** sees ** what has to happen to him, since he has to write it in code, making the developers gain a lot of time.
If there are too many global objects, and there are too many parameters in the functions that need them, you can always group your "global objects" into a class, style * factory *, that builds and returns the instance of the "global object" (simulated) that you want , passing the factory as a parameter to the objects that need the global object as dependence.
If you pass to test mode, you can always create a testing factory (which returns different versions of the same objects), and pass it as a parameter without having to modify the target class.
But is it always bad?
Not necessarily, there may be good uses for global variables. For example, constant values (the PI value). Being a constant value, there is no risk of not knowing its value at a given point in the program by any type of modification from another module. In addition, constant values tend to be primitive and are unlikely to change their definition.
It is more convenient, in this case, to use global variables to avoid having to pass the variables as parameters, simplifying the signatures of the functions.
Another can be non-intrusive "global" services, such as a logging class (saving what happens in a file, which is usually optional and configurable in a program, and therefore does not affect the application's nuclear behavior), or std :: cout,std :: cin or std :: cerr, which are also global objects.
Any other thing, even if its life time coincides almost with that of the program, always pass it as a parameter. Even the variable could be global in a module, only in it without any other having access, but that, in any case, the dependencies are always present as parameters.
Answer by: Peregring-lk
I'm currently playing about with some XNA stuff learning to program AI. Anyway, here's my situation: Class A has a function which takes a reference to an instance of class B, does some stuff to to it, and returns it. Class B contains an instance of Class A, and then calls the function from it.
Example in code:
Class A
{
B classB;
public A()
{
classB = new B();
}
public void Act()
{
this = B.Do(ref this);
}
}
Class B
{
public A Do(ref A classA)
{
//Manipulate
return classA;
}
}
I've tried passing a memberwise clone .. but that didn't work, obviously, because "this" is read-only. I've no idea with this. I'm really stuck. Does anybody have any ideas? I'd ideally like to avoid having to pass every single variable in the object as a separate argument, really.
Andy.
Classes are reference types, so doing
Class B
{
public void Do(A classA)
{
//Manipulate
}
}
should manipulate the object classA references. Then in A,
Class A
{
B classB;
public A()
{
classB = new B();
}
public void Act()
{
B.Do(this);
}
}
Note: "This does have the side effect that the reference of A that you pass cannot be set to null (it will only set the local variable to null)" - JulianR
Your B.Do() method does it (modifying an A) double by using the ref and a return. Neither is needed to modify classA. And because you target this it won't work anyway. You never assign to this, it makes no sense.
So the Simple answer is
class B
{
void Do(A anA) { anA.PublicProp = 1; }
}
But the circular referencing does make it a dubious design.
Is there something specific in //Manipulate that requires you to pass a class reference as ref? And why are you also returning classA as well - that seems to be redundent if you are using ref to begin with.
just remove the ref keyword. you only need ref if you want to change the argument into something else, if you just want to manipulate it, don't use the ref.
I think it would be bad (tricky to understand) if the language allowed you to change this into that, so it disallows what you've tried.
you cannot use "ref" with "this".
Why do you need the parameter to be passed by reference ?
You only need a "ref" parameter if your function must change which object the caller is refering to. If all you need is to manipulate and/or change the fields of the parameter then you do not need a ref parameter.
For more clarity, the whole thing is for behaviours for simple AI (EG chase, guard, evade etc). I'm wanting to pass the entire AI entity to the behaviours so that I can keep the behaviours separate for all entities (Sort of like a single style sheet for multiple web pages). The reason I want to pass the whole object is that some behaviours need certain parts of the object and some don't.
As for why I'm returning .. I don't quite know how I came to that decision. I'll remove it
Thank you very much, Derek E!
I just tested what you said, and it worked fine.
My problem, I think, is that I was thinking that when I passed the argument it made a clone of it and manipulated that instead, like (I think ..) it does in PHP or VB (can't remember which of those I was told it does it in)
Objects are always passed by reference and not by value. That is why we call classes in C# as reference types. Be careful if you are using structures instead since they are value types. A copy of the structure will be passed rather than the original. If you wish to pass the original then you must add the ref keyword. ref is only useful with objects if you wish to replace a reference to one object with a reference to another object.