Let's say I have a class called TestClass. I want the application to contain only one instance of this class at a time.
I have a heritable class name Singleton, I use it like this :
public class TestClass : Singleton<TestClass>
{
}
And I use it like this
TestClass.Instance // Gives me one instance
The thing is, from time to time, I'll need to re-instantiate the TestClass often, with new parameters etc..
Should I make a static instance and just re-instantiate whenever I want, or is there a better way to do this?
Thanks and sorry.
Singleton is meant to be existing until the app is terminated and shouldn't be re-instanitated. If you want to change any member of this class, create setter method.
For instance, if you have a singleton class and two members in it:
public int Integer1 { get; private set;}
public string String1 { get; private set;}
You can either create two setters or, if these two properties should be changed together, create one method which will set them a given values:
public void SetIntAndString(int int1, string str1)
{
Integer1 = int1;
String1 = str1;
}
There should never exist any way to delete or modify the class instance object itself.
Related
I am overlooking something simple I think. I have a form with a checkbox. I need to know if the checkbox is checked in a different cs file/class to know whether to make a column header Option1 or Option2.
Form1 (Public partial class) code:
public bool Checked
{
get
{
return checkBox1.Checked;
}
}
In my Export1 class I have private void CreateCell1 that takes in the data to be exported (creating an excel file from a datatable). The section of code I can't get to work is:
if (Form1.Checked.Equals("true"))
{
newRow["Option1"] = date2;
}
else
{
newRow["Option2"] = date2;
}
I am getting -Error 1 An object reference is required for the non-static field, method, or property 'Matrix1.Form1.Checked.get'
What did I overlook?
Well, the problem here is exactly what the compiler is telling you. You need an object reference in order to access the property.
Allow me to explain.
In C#, by default, class members (fields, methods, properties, etc) are instance members. This means that they are tied to the instance of the class they are a part of. This enables behavior like the following:
public class Dog
{
public int Age { get; set; }
}
public class Program
{
public static void Main()
{
var dog1 = new Dog { Age: 3 };
var dog2 = new Dog { Age: 5 };
}
}
The two instances of Dog both have the property Age, however the value is tied to that instance of Dog, meaning that they can be different for each one.
In C#, as with a lot of other languages, there are things called static members of classes. When a class member is declared static, then that member is no longer tied to an instance of the class it is a part of. This means that I can do something like the following:
public class Foo
{
public static string bar = "bar";
}
public class Program
{
public static void Main()
{
Console.WriteLine(Foo.bar);
}
}
The bar field of the Foo class is declared static. This means that it is the same for all instances of Foo. In fact, we don't even have to initialize a new instance of Foo to access it.
The problem you are facing here is that, while Form1 is not a static class and Checked is not a static property, you are treating it as such. In order for what you are trying to do to work, you need to create an instance of Form1 and access that instance's Checked property.
Depending on how your program is structured, there are many ways of doing this. If Form1 is created in the scope where you are trying to access Checked, then this will be straightforward. If Form1 is what spawns the new scope, then common practice is to pass a reference to it in the constructor.
For example, if Form1 creates a new Form2 then we do the following:
public class Form2 : Form
{
private Form1 parent;
public Form2(Form1 parent)
{
this.parent = parent;
InitializeComponent();
}
}
And then you can access parent throughout Form2. Of course, depending on the structure of your program, the exact implementation will be different. However, the general pattern is the same. Pass the reference to Form1, from the scope it was created in, to the new class, and then access it from there.
One way or another, you need to access the specific instance of Form1 that you're trying to check.
A few ways to do this are:
Pass the instance to the class constructor
Setting a public property of the other class to the instance of the form
Pass the instance to the method directly
For example:
public class SomeOtherClass
{
// One option is to have a public property that can be set
public Form1 FormInstance { get; set; }
// Another option is to have it set in a constructor
public SomeOtherClass(Form1 form1)
{
this.FormInstance = form1;
}
// A third option would be to pass it directly to the method
public void AMethodThatChecksForm1(Form1 form1)
{
if (form1 != null && form1.Checked)
{
// Do something if the checkbox is checked
}
}
// This method uses the local instance of the Form1
// that was either set directly or from the constructor
public void AMethodThatChecksForm1()
{
AMethodThatChecksForm1(this.FormInstance);
}
}
This class would need to be instantiated by the instance form1 using one of these methods:
// Pass the instance through the constructor
var someOtherClass = new SomeOtherClass(this);
// Or set the value of a property to this instance
someOtherClass.FormInstance = this;
// Or pass this instance to a method of the class
someOtherClass.AMethodThatChecksForm1(this);
I have a class defined as:
public class DatabaseEntity<T> where T : DatabaseEntity<T> {
public static string Query { get; protected set; }
public static IList<T> Load() {
return Database.Get(Query);
}
}
public class Node : DatabaseEntity<Node> {
static Node() {
Node.Query = #"SELECT Id FROM Node";
}
}
When I run Node.Load() from a codebehind (Window.xaml.cs) the Node's static constructor never fires; or at least doesn't hit a breakpoint and does not set Node.Query to anything other than null.
Is there any reason why this might occur?
Solution
Check out the answers below for a few solutions. For my case, I decided to simply make the Query variable public, and set all instances of Query in one place. (Not ideal, but it works.)
The problem lies in your assumptions about when a static constructor is called. The documentation, which isn't the clearest, states that
It is called automatically before the first instance is created or any static members are referenced.
You may assume that if you call
Node.Load();
that you are calling a static method on the Node class, but in fact you're calling it on the base class, as that is where it is implemented.
So, to fix this, you have two choices. First, you can trigger the static constructor explicitly by creating a new instance of the Node class prior to calling Load()
var foo = new Node(); // static ctor triggered
Node.Load();
or create a protected virtual member that the base class can call in order to get the query value (can't use abstract here, unfortunately)
public class DatabaseEntity<T> where T : Derp {
protected abstract string Query { get; }
public static IList<T> Load() {
return Database.Get(new DatabaseEntity<T>().Query);
}
}
Both of which are hacky. Better to dispense with the statics altogether and go with instance methods. Statics should be used sparingly, as they result in tight coupling and other design headaches such as this.
Yes, static constructors will not be called till the members of the class is first accessed or first instance is created.
In your case you're accessing DatabaseEntity<T>.Load, so static constructor of DatabaseEntity<T> will be called not its derived class ones.
Even though you call Node.Load it is mapped to DatabaseEntity<Node> at compile time. So technically you're not accessing Node class at all.
You can also call class constructors directly using System.Runtime.CompilerServices and the RuntimeHelpers type by doing something as follows:
RuntimeHelpers.RunClassConstructor(type.TypeHandle);
So for example you could use reflection to loop over all types in an inheritance chain and call each of the static constructors.
This is my class how hold my last visited Path:
public class LastPath
{
private static string _lastPath;
public static string lastPath
{
get { return _lastPath; }
set { _lastPath = value; }
}
}
If all members of a class is static and your class is not meant to instantiated it should be static.
In this case your class satisfies the above rule or guideline so marking it as static will make sense because you don't have any instance member.
LastPath path = new LastPath();
path.????// Nothing to access, so prevent instantiation by marking class static.
Being said that If you have only one field in your class and no methods I'd argue that you probably don't need a class at all, just refactor it to some other class where it would make sense.
make the class static and make a public property as static and you are done, like this:
public static class LastPath
{
public static string lastPath { get;set;}
}
I would say you to do this:
public static class LastPath
{
public static string lastPath
{
get;set;
}
}
You should declare it as static as static classes cannot be instantiated, while non static classes can be instantiated, which is not needed.
First - it looks odd to me to create class for holding single variable. Consider to use simple string variable lastVisitedPath instead. If you use this variable in single class, then make it field of that class.
Second - naming is not very readable. Here is how getting last path looks like: LastPath.lastPath. You see this useless duplication? Also keep in mind, that due to Microsoft naming guidelines public members should have Pascal Case names. Consider to create class with descriptive name like GlobalValues or Cache which reflects its purpose:
public static class GlobalValues // holds values which are globally accessible
{
public static string LastVisitedPath;
// other global values
}
So that usage will look like GlobalValues.LastVisitedPath or Cache.LastVisitedPath. Of course, if these classes don't supposed to be instantiated, they should be static.
Say i have
public int MyVariable;
in the Form1.cs file, and I want to access it from Class1.cs , what do you think would be the best way to do that?
Thanks!
MSDN: Properties
base class with property:
class Person
{
private string name; // the name field
public string Name // the Name property
{
get
{
return name;
}
set
{
name = value;
}
}
}
Auto Implemented Properties (if advanced work on "name" isn't needed):
class Person
{
public string Name { get; set; } // the Name property with hidden backing field
}
Class accessing the property:
Person person = new Person();
person.Name = "Joe"; // the set accessor is invoked here
System.Console.Write(person.Name); // the get accessor is invoked here
It depends on the scenario. But ideally, Form elements are passed to any functions that will need to use them.
You have a few options:
Pass the value to the class/method that's using it. This is the preferred scenario. If your class depends on this value, supply the value to the class. Don't make the class go looking for it. (See: Dependency Inversion Principle)
Make the value static. Then any other class can refer to that value. Note the difference between instance and static, of course. The value will always be the same and needs to be given in the definition of the member, not in a constructor or other logic.
Create an instance of the form (which is itself just a class) within the class and access the public member on that instance. This is unlikely to be what you want because the instance you're creating isn't the instance that's running "on the page." (It also violates the principle noted above.)
Pass a reference to the form (this) to the class and refer to the member from that reference.
On a side note, you'll want to get in the habit of making your public members properties instead of variables. In most cases, the property will likely just get/set the variable and nothing more. However, if something more ever needs to be added it can be done so without breaking compatibility. Changing a variable to a property changes the footprint of the class and breaks things which use that class.
Make the variable static. Then you can call it like Form1.MyVariable.
Try like this:
In case (1) you can have MyClass.MyInt private readonly.
public class MyForm : System.Windows.Forms.Form
{
int myInt;
public MyForm()
{
myInt = 1;
//1
var myClass = new MyClass(myInt);
//2
myClass.MyInt = myInt;
}
}
public class MyClass
{
public int MyInt { get; set; }
public MyClass(int myInt)
{
MyInt = myInt;
}
}
Is there anyway of having a base class use a derived class's static variable in C#? Something like this:
class Program
{
static void Main(string[] args)
{
int Result = DerivedClass.DoubleNumber();
Console.WriteLine(Result.ToString()); // Returns 0
}
}
class BaseClass
{
public static int MyNumber;
public static int DoubleNumber()
{
return (MyNumber*2);
}
}
class DerivedClass : BaseClass
{
public new static int MyNumber = 5;
}
I'm trying to have it return 10, but I'm getting 0.
Here's where I'm using this: I have a class called ProfilePictures with a static function called GetTempSavePath, which takes a user id as an argument and returns a physical path to the temp file. The path base is a static variable called TempPath. Since I'm using this class in multiple projects and they have different TempPaths, I'm creating a derived class that sets that variable to whatever the path is for the project.
See Also
Why can’t I declare C# methods virtual and static?
Apart from the fact that has already been pointed out... that static variables are tied or bound to the specific class declaring them and cannot be overridden. Overriding/Polymorphism needs instances to work.
Your problem can be solved with a change in design.
string ProfilePictures.GetTempSavePath(SomeType UserId, string sBasePath)
if it just needs these 2 variables to compute the return value, you can keep it as a utility/static method. Now you can feed in different base paths..
Now it seems from your question, that you need to use this class in multiple projects (which have fixed base paths) and kind of hardcode the base path so that you dont have to specify it for each call.
Type/Class hierarchies should be defined based on behavior and not on data. Variables can handle change in data. Hence I'd suggest holding the basepath value as a static member variable, which is initialized from a resource file (DoubleClick your project properties node > Settings > Add a new Settings file > add a new setting called BasePath - string - Application scope - VALUE=C:\Users). Now you just need to tweak the app.config file for each project, no code changes, no hardcoding and not more than one type needed.
public class PathHelper
{
static string _sBasePath;
static PathHelper()
{
_sBasePath = Properties.Settings.Default.BasePath;
}
static string GetTempSavePath(string sUserId)
{
// dummy logic to compute return value, replace to taste
return Path.Combine(_sBasePath, sUserId.Substring(0, 4));
}
}
Hope that made sense
The problem is that you're re-declaring the static variable in the derived class. The MyNumber declaration in DerivedClass hides the declaration in the base class. If you remove that declaration, then references to the "MyNumber" in derived class static functions will refer to the base class variable. Of course, if you remove the declaration then you can't use a static initializer in the derived class.
You might want to consider requiring users to instantiate an instance of ProfilePictures rather than provide a static function for GetTempSavePath. That way you could overide the GetTempSavePath method to provide the correct TempPath. Or, you could simply set the value of the static path value in your derived class constructor.
Although it is possible to use inheritance with static members, you can't relly have polymorphic behavior without a "this" pointer.
Static members are not virtual, so you can not override them.
When you call DerivedClass.DoubleNumber you are actually calling BaseClass.DoubleNumber as the DerivedClass class doesn't have that method. Also, the use of MyNumber in that method is always going to be BaseClass.MyNumber no matter how you call the method.
What you are looking for is a virtual property that you can override in a derived class. As a virtual member can not be static, you need to use an instance of the class. If it's not practical to keep a reference to the instance, you can use the singleton pattern.
This kinda works:
public class ClassA
{
protected static int num = 5;
public static int GetNum()
{
return num;
}
}
public class ClassB : ClassA
{
static ClassB()
{
num = 6;
}
}
However, note the difference when you call ClassB.GetNum() before and after instantiating one object. The static initializer doesn't run until you create at least one, so you'll get 5 if nothing has been created, and 6 if at least one object has.
Provide a virtual method that returns the class static.
class BaseClass
{
public virtual int GetMyNumber() { return MyNumber; }
}
You might want to use a virtual property instead...
Using too much of static members is also not recommended if they are going to encapsulate a logic of an entire object. For example your code can be rewritten correctly in following manner... and this is the most recommended in oops,
class Program
{
static void Main(string[] args)
{
int Result = DerivedClass.Instance.DoubleNumber();
Console.WriteLine(Result.ToString()); // Returns 0
}
}
class BaseClass
{
protected BaseClass(){} // this enforces that it can not be created
public int MyNumber;
public virtual int DoubleNumber()
{
return (MyNumber*2);
}
}
public class DerivedClass : BaseClass
{
// this also ensures that it can not be created outside
protected DerivedClass(){
MyNumber = 5;
}
// only way to access this is by Instance member...
public static DerivedClass Instance = new DerivedClass();
}
This is how we access configuration values and many other single instance static objects provided by .Net Library.