Is it bad practice to put most variables at class level in a Form? Would these be considered global variables?
public partial class Form1 : Form
{
private string mode;
private int x, y;
public Form1()
{
InitializeComponent();
}
}
I'm using the variables in multiple controls when I declare them at class level.
What i get from the question is that if you are using as a Individual form that is not dependent on any form then all this variables will be private variables to the class. And if the form is called from somewhere else. Then also it will be private variables. If you really want to make a clear design then you can Create public properties over private variables that you want to expose to other class.
In that way you can put a limit access to the other class to the private variables by creating read only properties so that other classes cannot modify but can access it.
Those would be considered class-level globals (to distinguish from application globals.) The more important distinction in this case is that they are private to the class.
Class-level globals have their uses, so I definitely wouldn't call it a bad practice. A very good use for private class globals is when you plan to expose them through property accessors. For example:
public readonly properties whose values are controlled by logic internal to your class.
public properties with both set and get accessors (enabling custom validation logic in setter.)
However, I would say it's a good practice to make things local unless otherwise necessary. The reason is that you have less mutable state belonging to a class instance, so there is less potential for bugs like this:
private int EvilMethod1() {
x = (int) Math.Pow((double) y, 2);
return x;
}
private int EvilMethod2() {
y = (x + y) * 2;
return y;
}
// Assignments depend on the current values of x and y,
// as well as yielding unexpected side effects.
private void PureEvil()
{
// Return value depends on current y; has side effect on x while assigning y.
y = EvilMethod1();
// Return value depends on current x and y; has side effect on y while assigning x.
x = EvilMethod2();
}
Those aren't considered global variables. They are global only within the Form1 class, not the entire program.
It depends what the variables are used for.
If they are only used within a single method they should be local to that method.
If they describe the state of the class and are used in multiple places they should be declared as class members.
They are private to the class Form1
Without knowing what the intent of your form is, it's hard to say whether what you're doing is good or bad. The variables shown here have class scope, and since they are private, they are not accessible outside of Form1 and are not considered "global."
If you truly want global variables, create a static class with private static variables and public static accessors/mutators (a property in C#), and access the variable through the public property. See this answer for an example.
Related
I am a little confused about the Simplient thing variables. I have an ASP.NET Page (not MVC).
I want to create a variable at the class level which by definition is field variable because it is within a class. Example: I have a page called example.aspx and in the code behind I have about 10 different methods. I need each method to access the variable.
The key here is, I will not be accessing this variable from any other file or page:
Which is the right way?
public partial class example : System.Web.UI.Page
{
private bool firstField;
public bool FirstField
{
get { return firstField; }
set { firstField = value; }
}
OR; because this variable will not be access outside of the page or class do I simply do this:
public partial class example : System.Web.UI.Page
{
bool firstField;
I understand the use of the property for global variables but do I need to use it if the variable will not be accessed outside of a class? (My books says nothing about this part).
If you have a data member that you don't want to be accessible to other classes, then you can explicitly make it a simple private field. If you want to add logic to its read and write operations, make a private field but access it through a private property.
In any case, if you want to encapsulate the member to make it accessible only to the class, you'll have to make it private and not expose it through any public members.
The first example will allow access to firstField, as you are creating a public getter/setter which sets it value;
If firstfield is only to be used within the example class, you can make it private i,e,
private bool firstfield;
I'm trying to develop an application on which I have an MDIParent and several MDIchilds. I would like to create a global variable on my MDIParent, and I want that variable to be accessible from its children.
How can I do that??
If Matthew Watson's answer isn't what you're after...
If you just want your "global" variable to be accessible to the children of a particular MDI parent form, then just use a regular instance property on it. The children will be able to access it through child.MdiParent.MyVariable (after casting MdiParent to the appropriate type). For example:
class ParentForm
{
public int MyVariable
{
return 1;
}
}
class ChildForm
{
public void MyMethod()
{
var parent = this.MdiParent as ParentForm;
foo = parent.MyVariable;
}
}
A quick note: it's generally best to avoid using "global" variables (i.e. static fields/properties) as much as possible. Keep all the different parts of your program's state confined to the appropriate context to reduce coupling. See the Law of Demeter.
A global variable in C# is effectively a static field or property.
So just add a public static property to MDIParent:
public static int MyGlobalInt
{
get
{
return 42;
}
}
That will be shared among ALL instances of MDIParent. If that's not what you meant, then it's not a global you want.
class CoOrds
{
public int x, y;
public CoOrds() {
x = 0;
y = 0;
}
public CoOrds(int x, int y) {
this.x = x;
this.y = y;
}
}
public CoOrds toto() {
CoOrds B = new CoOrds(3, 2);
return B;
}
private void result_Click(object sender, EventArgs e) {
l6.Text = "";
CoOrds D = new CoOrds();
D = toto();
l6.Text = "(" + D.x + "," + D.y + ")";
}
I get following error:
Error 2 Inconsistent accessibility: return type 'johny.Form1.CoOrds' is less accessible than method 'johny.Form1.toto()
As your CoOrds class is nested within Form1, it is by default private (ie. for use only within the Form1 class). The easiest solution would be to make your CoOrds class public.
public class CoOrds{
public int x, y; // ...
Another alternative would be to simply un-nest the CoOrds class, namely, move the declaration of the class outside of your Form1 class entirely.
Original answer (before I noticed that it's a nested type)
Yes - presumably Form1 and Form1.toto() are both public - whereas Coords is private (the default accessibility for non-nested types). You can't create a method with a return type or parameter type which isn't accessible to all the code which can see the method - it doesn't make sense.
Options:
Make Form1 internal
Make Form1.toto() internal
Make Coords public
Personally I'd recommend making Form1 internal if you can - it's rare that a form needs to be available to other code, beyond unit tests (for which I'd use InternalsVisibleTo). Making Form1.toto() internal would be equally fine. I prefer to keep types and members as private as I can, so I'd only make Coords public as a last resort.
I'd also strongly recommend that you start following .NET naming conventions, and provide more informative names than toto(). Oh, and avoid public fields - expose properties instead. You may well want to make it immutable, too.
Having noticed that it's a nested type...
It actually looks like Coords is a nested class within Form1, which will mean it's private by default. It's unusual to want to expose a nested class - and it doesn't look like it's really tightly tied to Form1 anyway. I would suggest making it a top-level (non-nested) type in the first place.
I'm pretty new to C# and I was trying out a few things. I have a label (named 'newLabel') in the form1.cs. I have a class named 'methods.cs'. In this class I have the method
public static void updateLabel()
what I want to do is:
public static void updateLabel()
{
newLabel.Text = "New Value";
}
but this doesn't work, probably because the method is in methods.cs and the newLabel is in form1.cs.
I had the same problem with declared variables. In the methods.cs I had the variable
int value;
but I couldn't use this variable in form1.cs. I fixed this by doing
public static int value { get; set; }
I have no idea what that did but it works, but I don't know how I can apply this trick with the label.
Could someone help me with this?
Thanks!
You should read up about OOP and encapsulation. Basically you want the form
to access private fields in another object (your class) - this is restricted by encapsulation, that's why you are running into problem - you can get around them by adding those fields and methods to the "public" interface that your class is declaring by making them public properties and methods, i.e in your example:
public int Value {get;set;}
Sometimes composition is used, i.e. in your example since your class is directly accessing the form you could have a form property on your class:
public Form ViewForm {get;set;}
It would be best if you learnt C# from tutorials, but the answer to this particular question lies with something called "scope"
Essentially, scope is the visibility of variables, classes, functions and objects. A variable marked "private" can only be seen within the thing that created it (if it's created inside a function it will always be private and any variables defined inside a function can only be used inside that function). If it's created inside a class only that class can use it.
Variables or functions denoted as public (this can only be done inside a class) can be seen from outside that class. To do that you would invoke myClass.myVariable to access the variable or myClass.myFunction() to access the function.
To denote the visibility of an object you use the keywords "public" or "private". Note: This only applies to variables and functions inside classes (it also applies to other things within classes, such as nested classes and structs, but that's outside the scope of this basic intro).
for example:
class myClass
{
private int myInt;
public void myfunction()
{
myInt = 1;
}
}
This will work, as myInt can be seen by anything inside myClass
class myOtherClass
{
private void myfunction()
{
myClass myObject = new myClass();
myObject.myInt = 2;
}
}
This will not, as myInt is private to myObject and only myObject can change it. myOtherClass does not have permission and it cannot see it.
class myOtherClassTwo
{
private void myfunction()
{
myClass myObject = new myClass();
myObject.myFunction();
}
}
This, thankfully, will work. myFunction was set as public in the myClass class, so it can be seen by anybody outside of the class.
Now the keyword static which you use has a whole different meaning. I advise you not to use it until you've learned about it as you're only adding additional complexity to your problems.
I hope this has cleared things up, though I must urge you to follow some real tutorials as these basics must be thoroughly detailed or you'll be caught out later on.
Since your updateLabel method accesses the label inside the form, correct object-oriented design would dictate that this method should be in the form, too. Then you have no problem accessing newLabel.
Technically speaking: newLabel doesn’t mean anything outside a form object. You could have several copies of your form, which would mean several copies of your newLabel; which of them should it refer to? Of course the computer won’t take a guess there; it’ll expect that you tell it which form you want to use.
The reason you couldn’t access the value variable is because it was private. If you had changed it simply to:
public static int value;
then it would have worked.
From the Form1, call the updateLabel method in the mothods class:
methods updateMethod = new methods();
newLabel.Text = updateMethod.updateLabel();
With this method in the methods class:
public static string updateLabel(){
return "New Value";
}
I've got a wrapper class which encapsulates a piece of information that needs to be transmitted as a byte array.
In that way, the class encapsulates the necessary header (with fields like DATA_LENGTH or MESSAGE_TYPE) into the corresponding byte positions. For that I want to define positions and length in constants, for example:
HEADER_DATA_LENGTH_IX = 0;
HEADER_DATA_LENGTH_LENGTH = 2;
which means DATA_LENGTH starts at 0 and takes two bytes.
but so far I'm struggling with making them constants or static readonly fields. Const cannot be protected, therefore I won't be able to derive a new class and change the constants if a use them, on the other way I might declare new constants in the derived class and the use them.
What will be your approach?
If you want to change the value of these params in a derived class, you can make them readonly and change them in the constructor of the derived class
I wouldn't make them const anyhow, because they're not...
The basic difference is when the variable is initialized. 'readonly' is set at initialization, or in the contructor, while 'const' is set at compile time.
I think the big decision is if you want to inherit the class and override the value. If you do, go readonly. Otherwise I don't think it really matters.
readonly C#ref: http://msdn.microsoft.com/en-us/library/acdd6hb7.aspx
const C# ref: http://msdn.microsoft.com/en-us/library/e6w8fe1b.aspx
Create an inner class with the constants. The deriving classes can then later override the inner class and change the constants as necessary.
e.g. base class:
public class Stuff
{
public class HeaderInformation
{
public const int HEADER_DATA_LENGTH_IX = 0;
public const int HEADER_DATA_LENGTH_LENGTH = 2;
}
}
Then the derived class can do this:
public class DerivedStuff : Stuff
{
public new class HeaderInformation : Stuff.HeaderInformation
{
public new const int HEADER_DATA_LENGTH_IX = 10;
}
}
This way, you have flexibility. In DerivedStuff, the HeaderInformation class has all of the constants in the base Stuff.HeaderInformation class, but can change any of them, or keep the ones it has.
This exact question is answered by the official c# faq on msdn
I wouldn't make these constant because they simply aren't constants. When declaring something as const you should ask yourself: can this change? Your message lengths might change one day, so they are better to be made readonly.