I am trying to create a class to hold all my global constants, e.g.:
namespace MyProj
{
public static class Constants
{
public const string MY_STRING = "this needs to be used ad nauseum";
}
}
This works great. However, the result is that in code I have to always type:
doSomethingWith(Constants.MY_STRING);
When what I really want to be able to do is go (something like):
using MyProj.Constants;
doSomethingWith(MY_STRING);
How can I achieve this?
Add static to your using:
using static MyProj.Constants;
Details here.
Related
How do I declare a variable so that every class (*.cs) can access its content, without an instance reference?
In C# you cannot define true global variables (in the sense that they don't belong to any class).
This being said, the simplest approach that I know to mimic this feature consists in using a static class, as follows:
public static class Globals
{
public const Int32 BUFFER_SIZE = 512; // Unmodifiable
public static String FILE_NAME = "Output.txt"; // Modifiable
public static readonly String CODE_PREFIX = "US-"; // Unmodifiable
}
You can then retrieve the defined values anywhere in your code (provided it's part of the same namespace):
String code = Globals.CODE_PREFIX + value.ToString();
In order to deal with different namespaces, you can either:
declare the Globals class without including it into a specific namespace (so that it will be placed in the global application namespace);
insert the proper using directive for retrieving the variables from another namespace.
You can have static members if you want:
public static class MyStaticValues
{
public static bool MyStaticBool {get;set;}
}
First examine if you really need a global variable instead using it blatantly without consideration to your software architecture.
Let's assuming it passes the test. Depending on usage, Globals can be hard to debug with race conditions and many other "bad things", it's best to approach them from an angle where you're prepared to handle such bad things. So,
Wrap all such Global variables into a single static class (for manageability).
Have Properties instead of fields(='variables'). This way you have some mechanisms to address any issues with concurrent writes to Globals in the future.
The basic outline for such a class would be:
public class Globals
{
private static bool _expired;
public static bool Expired
{
get
{
// Reads are usually simple
return _expired;
}
set
{
// You can add logic here for race conditions,
// or other measurements
_expired = value;
}
}
// Perhaps extend this to have Read-Modify-Write static methods
// for data integrity during concurrency? Situational.
}
Usage from other classes (within same namespace)
// Read
bool areWeAlive = Globals.Expired;
// Write
// past deadline
Globals.Expired = true;
A useful feature for this is using static
As others have said, you have to create a class for your globals:
public static class Globals {
public const float PI = 3.14;
}
But you can import it like this in order to no longer write the class name in front of its static properties:
using static Globals;
[...]
Console.WriteLine("Pi is " + PI);
I want to create an alias for a class name. The following syntax would be perfect:
public class LongClassNameOrOneThatContainsVersionsOrDomainSpecificName
{
...
}
public class MyName = LongClassNameOrOneThatContainsVersionOrDomainSpecificName;
but it won't compile.
Example
Note This example is provided for convenience only. Don't try to solve this particular problem by suggesting changing the design of the entire system. The presence, or lack, of this example doesn't change the original question.
Some existing code depends on the presence of a static class:
public static class ColorScheme
{
...
}
This color scheme is the Outlook 2003 color scheme. i want to introduce an Outlook 2007 color scheme, while retaining the Outlook 2003 color scheme:
public static class Outlook2003ColorScheme
{
...
}
public static class Outlook2007ColorScheme
{
...
}
But i'm still faced with the fact that the code depends on the presence of a static class called ColorScheme. My first thought was to create a ColorScheme class that I will inherit from either Outlook2003 or Outlook2007:
public static class ColorScheme : Outlook2007ColorScheme
{
}
but you cannot inherit from a static class.
My next thought was to create the static ColorScheme class, but make Outlook2003ColorScheme and Outlook2007ColorScheme classes non-static. Then a static variable in the static ColorScheme class can point to either "true" color scheme:
public static class ColorScheme
{
private static CustomColorScheme = new Outlook2007ColorScheme();
...
}
private class CustomColorScheme
{
...
}
private class Outlook2008ColorScheme : CustomColorScheme
{
...
}
private class Outlook2003ColorScheme : CustomColorScheme
{
...
}
but that would require me to convert a class composed entirly of readonly static Colors into overridable properties, and then my ColorScheme class would need to have the 30 different property getters thunk down into the contained object.
That's just too much typing.
So my next thought was to alias the class:
public static ColorScheme = Outlook2007ColorScheme;
But that doesn't compile.
How can I alias a static class into another name?
Update: Can someone please add the answer "You cannot do this in C#", so I can mark that as the accepted answer. Anyone else wanting the answer to the same question will find this question, the accepted answer, and a number of workarounds that might, or might not, be useful.
I just want to close this question out.
You can’t. The next best thing you can do is have using declarations in the files that use the class.
For example, you could rewrite the dependent code using an import alias (as a quasi-typedef substitute):
using ColorScheme = The.Fully.Qualified.Namespace.Outlook2007ColorScheme;
Unfortunately this needs to go into every scope/file that uses the name.
I therefore don't know if this is practical in your case.
You can make an alias for your class by adding this line of code:
using Outlook2007ColorScheme = YourNameSpace.ColorScheme;
You cannot alias a class name in C#.
There are things you can do that are not aliasing a class name in C#.
But to answer the original question: you cannot alias a class name in C#.
Update: People are confused why using doesn't work. Example:
Form1.cs
private void button1_Click(object sender, EventArgs e)
{
this.BackColor = ColorScheme.ApplyColorScheme(this.BackColor);
}
ColorScheme.cs
class ColorScheme
{
public static Color ApplyColorScheme(Color c) { ... }
}
And everything works. Now i want to create a new class, and alias ColorScheme to it (so that no code needs to be modified):
ColorScheme.cs
using ColorScheme = Outlook2007ColorScheme;
class Outlook2007ColorScheme
{
public static Color ApplyColorScheme(Color c) { ... }
}
Ohh, i'm sorry. This code doesn't compile:
My question was how to alias a class in C#. It cannot be done. There are things i can do that are not aliasing a class name in C#:
change everyone who depends on ColorScheme to using ColorScheme instead (code change workaround because i cannot alias)
change everyone who depends on ColorScheme to use a factory pattern them a polymorphic class or interface (code change workaround because i cannot alias)
But these workarounds involve breaking existing code: not an option.
If people depend on the presence of a ColorScheme class, i have to actually copy/paste a ColorScheme class.
In other words: i cannot alias a class name in C#.
This contrasts with other object oriented languages, where i could define the alias:
ColorScheme = Outlook2007ColorScheme
and i'd be done.
You want a (Factory|Singleton), depending on your requirements. The premise is to make it so that the client code doesn't have to know which color scheme it is getting. If the color scheme should be application wide, a singleton should be fine. If you may use a different scheme in different circumstances, a Factory pattern is probably the way to go. Either way, when the color scheme needs to change, the code only has to be changed in one place.
public interface ColorScheme {
Color TitleBar { get; }
Color Background{ get; }
...
}
public static class ColorSchemeFactory {
private static ColorScheme scheme = new Outlook2007ColorScheme();
public static ColorScheme GetColorScheme() { //Add applicable arguments
return scheme;
}
}
public class Outlook2003ColorScheme: ColorScheme {
public Color TitleBar {
get { return Color.LightBlue; }
}
public Color Background {
get { return Color.Gray; }
}
}
public class Outlook2007ColorScheme: ColorScheme {
public Color TitleBar {
get { return Color.Blue; }
}
public Color Background {
get { return Color.White; }
}
}
try this:
using ColorScheme=[fully qualified].Outlook2007ColorScheme
I'm adding this comment for users finding this long after OP accepted their "answer".
Aliasing in C# works by specifying the class name using it's fully qualified namespace. One defined, the alias name can be used within it's scope.
Example.
using aliasClass = Fully.Qualified.Namespace.Example;
//Example being the class in the Fully.Qualified.Namespace
public class Test{
public void Test_Function(){
aliasClass.DoStuff();
//aliasClass here representing the Example class thus aliasing
//aliasClass will be in scope for all code in my Test.cs file
}
}
Apologies for the quickly typed code but hopefully it explains how this should be implemented so that users aren't mislead into believing it cannot be done in C#.
Aliasing the way that you would like to do it will not work in C#. This is because aliasing is done through the using directive, which is limited to the file/namespace in question. If you have 50 files that use the old class name, that will mean 50 places to update.
That said, I think there is an easy solution to make your code change as minimal as possible. Make the ColorScheme class a facade for your calls to the actual classes with the implementation, and use the using in that file to determine which ColorScheme you use.
In other words, do this:
using CurrentColorScheme = Outlook2007ColorScheme;
public static class ColorScheme
{
public static Color ApplyColorScheme(Color c)
{
return CurrentColorScheme.ApplyColorScheme(c);
}
public static Something DoSomethingElse(Param a, Param b)
{
return CurrentColorScheme.DoSomethingElse(a, b);
}
}
Then in your code behind, change nothing:
private void button1_Click(object sender, EventArgs e)
{
this.BackColor = ColorScheme.ApplyColorScheme(this.BackColor);
}
You can then update the values of ColorScheme by updating one line of code (using CurrentColorScheme = Outlook2008ColorScheme;).
A couple concerns here:
Every new method or property definition will then need to be added in two places, to the ColorScheme class and to the Outlook2007ColorScheme class. This is extra work, but if this is true legacy code, it shouldn't be a frequent occurence. As a bonus, the code in ColorScheme is so simple that any possible bug is very obvious.
This use of static classes doesn't seem natural to me; I probably would try to refactor the legacy code to do this differently, but I understand too that your situation may not allow that.
If you already have a ColorScheme class that you're replacing, this approach and any other could be a problem. I would advise that you rename that class to something like ColorSchemeOld, and then access it through using CurrentColorScheme = ColorSchemeOld;.
I suppose you can always inherit from the base class with nothing added
public class Child : MyReallyReallyLongNamedClass {}
UPDATE
But if you have the capability of refactoring the class itself: A class name is usually unnecessarily long due to lack of namespaces.
If you see cases as ApiLoginUser, DataBaseUser, WebPortalLoginUser, is usually indication of lack of namespace due the fear that the name User might conflict.
In this case however, you can use namespace alias ,as it has been pointed out in above posts
using LoginApi = MyCompany.Api.Login;
using AuthDB = MyCompany.DataBase.Auth;
using ViewModels = MyCompany.BananasPortal.Models;
// ...
AuthDB.User dbUser;
using ( var ctxt = new AuthDB.AuthContext() )
{
dbUser = ctxt.Users.Find(userId);
}
var apiUser = new LoginApi.Models.User {
Username = dbUser.EmailAddess,
Password = "*****"
};
LoginApi.UserSession apiUserSession = await LoginApi.Login(apiUser);
var vm = new ViewModels.User(apiUserSession.User.Details);
return View(vm);
Note how the class names are all User, but in different namespaces. Quoting PEP-20: Zen of Python:
Namespaces are one honking great idea -- let's do more of those!
Hope this helps
Is it possible to change to using an interface?
Perhaps you could create an IColorScheme interface that all of the classes implement?
This would work well with the factory pattern as shown by Chris Marasti-Georg
It's a very late partial answer - but if you define the same class 'ColorScheme', in the same namespace 'Outlook', but in separate assemblies, one called Outlook2003 and the other Outlook2007, then all you need to do is reference the appropriate assembly.
The best way I've found to simulate alias in C# is inheritance.
Create a new class that inherits from the original class:
public class LongClassNameOrOneThatContainsVersionsOrDomainSpecificName
{
...
}
public class MyName
: LongClassNameOrOneThatContainsVersionOrDomainSpecificName
{
}
The only thing that you would need to be careful is the constructor. You need to provide a a constructor for MyName class.
public class MyName
: LongClassNameOrOneThatContainsVersionOrDomainSpecificName
{
public MyName(T1 param1, T2 param2) : base(param1, param2) {}
}
In this example I'm using T1 and T2 as generic types, since I don't know the constructor for your LongClassNameOrOneThatContainsVersionOrDomainSpecificName class.
Beware, though, that this is not alias. Doing this to you application might run into some issues or problems. You might need to create some extra code to check for types, or even overload some operators.
I have a static ExceptionHelper that looks like this:
public static class ExceptionHelper
{
public static async void ShowDialog(string message)
{
// Show message
}
}
Whenever I want to call this method I do it like this at the moment:
ExceptionHelper.ShowDialog("This is a message.");
I now thought of defining an alias for the ExceptionHelper to not having to write the whole word each time I want to use it.
I know I can achieve it with using:
using Ex = MyNamespaces.ExceptionHelper;
But then I'd have to define it in each file I want to use the method. Is there a way I can define the alias globally without changing the name of the class? Or is there any attribute I can set above the class declaration?
Extension Method
You could make it an extension method on string.
public static class ExceptionHelper
{
public static async void ShowDialog(this string message)
{
// Show message
}
}
Then you would use it like so:
using WhateverNamespaceExceptionHelperLivesIn;
public class TestClass
{
public void TestMethod()
{
"This is a message".ShowDialog();
}
}
This makes your question moot - you don't have to define an alias at all.
Static imports
An alternative approach is to import the class statically. You won't need an alias, because you can reference the ShowDialog method directly. This will require C#6/Visual Studio 2015.
using static WhateverNamespaceExceptionHelperLivesIn.ExceptionHelper;
public class TestClass
{
public void TestMethod()
{
ShowDialog("This is a message");
}
}
In C# 6.0 you can use static usings:
using static MyNamespace.ExceptionHelper;
Of course not globally, that works only for defines. But in a file where you use this line, you can use the members of the ExceptionHelper without any prefix.
As of C# 10, you can now define gloabl usings.
// GlobalUsing.cs
global using static WhateverNamespaceExceptionHelperLivesIn.ExceptionHelper;
And it will now be available globally, without having to define the class name, or the namespace, at the top of each class.
// Available Globally in the Project
public class TestClass
{
public void TestMethod()
{
ShowDialog("This is a message");
}
}
This might apply, even though you are using a method. You could use an ENUM type instead that lies outside of any namespace and access globals values that way. Place the enum in a file outside of any namespace. You can access it globally that way, or if you have trouble, using the "global" keyword below if you have any trouble referencing it:
enum Size
{
SMALL = 1,
MEDIUM = 5,
LARGE = 10
}
class Test {
int mysize1 = (int)Size.SMALL;
int mysize2 = (int)global::Size.MEDIUM;
}
namespace MyStyle
{
public class Styles
{
//intended to store style.properties & style.values class
public sealed class sealdPropsClass
{
public sealed const string DarkBlueColor = "darkBlue";
}
public static class staticPropsClass
{
public static const string LightBlueColor = "lightBlue";
}
}
}
accessing like so :
using MyStyles;
string ColorBlue = Styles.sealedPropsClass.DarkBlueColor;
in another question about classes and inheritance
I had been warned to refrain the static modifier
reason is : it would be un accessible to others while The Current user
is already Accessing the class
via current page or another web application that uses that class .
what i would like to understand from this example:
1.
How Can i wrap Styles in an outer class(is that what i Should do?) :
so i would be able to use an instance = a clone, of the subject class as in this code below:
public Styles CurrentAppStyles = new Styles();
string darkColor = CurrentAppStyles.sealdPropsClass.DarkBlueColor
2.
if i am importing MyStyle namespace via
using MyStyle; ///<-- is that an instance ?
meaning it would not (if there was an Exeption error for that case) alert user:
"Styles.SealedPropsClass.DarkBlueColor is Currently being used, Please try again later..."
or it is actually instantiating the Whole namespace (that's what i think happens in this case)
and thanks for the Great help i can get here , from your experience and Knowledge !!
updated (source of Question)
this is where i have been warned , could you pleas shed some more light ???
This isn't answering your question but I noticed this hasn't been pointed out yet: your mail class is dangerous because it is declared static and has public static fields exposed. **
** update 2** my fault was that i didn't get from Joshuas comment is actually
sharing the state globally was the issue rather access issue... so , i guess in the case of using constant fields (strings etc...) would not be a problem
so what i can understand by now that using a static class is not to be avoided at all scenarios
for example . extention methods are used via a static class , most of my sub classess are static for example :"
public class container // instanciated so name is not so relevant
{ // e.g : container c = new container()
// usage- c.utils.......
public static class utils // used from an instance of container
{
public static int Str2int(string strToConvert)
{
return Convert.ToInt32(StrToConvert);
}
}
}
When writing this post i was checking all questions asked with related subject
and couldent find a simple answer to this Newbs C# issue
i would like ... if i may , to have as much as it can be a well-explaind answer (Please!)
i made a public static class
public static class MyLoadedBtmpToolBox
{
public static string FnameToLoad;
public static bool PutLoadedByteArrInPicbox;
public static string[] LoadedRefrnce;
public static int SourceX_Loaded, SourceY_Loaded, RectWidth_Loaded, RectHeight_Loaded;
---> public static int tst = Str2Int(LoadedRef[0]);
public static byte[] LoadedByteArr;
}
this calss as usually does by default, is within the main form i am using
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using System.Threading;
using System.Diagnostics;
using System.Drawing.Imaging;
using System.IO;
using System.Security.Cryptography;
using WindowsInput;
namespace MyScrCupTry1
{
public partial class MyForm1 : Form
{
public static class MyLoadedBtmpToolBox
{
public static int testStr2Int = Str2Int("100");
}
public int Str2Int(string STR)
{
int strInt = Convert.ToInt32(null);
if (isntEmpty(STR))
{
strInt = Convert.ToInt32(STR);
}
else
{
MessageBox.Show("theString " + STR + " is Null");
}
return strInt;
}
}
i can't assing the testStr2Int a value , by using my public "helper Method" Str2Int() from the main form
i am Getting Error :
Error 1 An object reference is required for the non-static field, method, or property 'MyScrCupTry1.MyForm1.Str2Int(string)' G:\RobDevI5-Raid-0\Documents\Visual Studio 2010\Projects\WindowsFormsApplication2\WindowsFormsApplication2\MyForm1.cs 95 45 MyScrCuptry1
What is the right way for accessing Main Form Public elemets from a static Class
if it is possible / (not illegal)...
ReEditing
after Those two answers ...
I tried to implement
the code from first answer without expected results i guess i didn't know the right code structure with override OnLoad(..) thing ...
BUT !
i have turnd the method Str2Int(STR) from public into public static
so now elements from the form itself still have access (i am surprised) to Str2Int()
and from the static Class I Can Access it too....
and its all thanks tp making it into static too ,
am i missing somthing else is there "hidden" drawback when changing Str2Int() from public into public static ?
The point of static code is that belongs to itself, rather than any other object. For this to be true, when you set something as static, everything that depends on it must also be static!
This is what your error message is trying to tell you. You are declaring something as static, but in the computation of that static, you are using something that is not static. Str2Int is not tagged as static, so that is an immediate problem, and it's possible that LoadedRef is also not static. I am half-sure you actually meant to use LoadedRefrnce there, in which case you're fine, but since you spelled nothing correctly I can't be sure!
Check this page for an explanation of the static keyword, also please make more of an effort to read up on C# coding conventions - this makes it much easier for people to read your code when you ask for help like this!
Expanding upon the edits above:
The 'drawback' to making code static is that it pretty much instantly makes everything it is a part of untestable. The idea behind unit testing is to have all of your code broken out into totally replaceable parts, so they can be tested separately and moved out separately (if need be). By making a bunch of code static, you are essentially welding it to any other code it might be a part of. In your own example, by making Str2Int() public static, everything that uses Str2Int() is now untestable!
Static code is, generally speaking, a vice that you should attempt to avoid as much as possible. There are places where you can't, and if you are just starting to learn really the biggest focus is just getting something working. But be ready to look back on this code and go cold at how you could've ever written something so bad in a few years, when you are more experienced and confident in your skills.
add Form object to static class, like this :
public static class MyLoadedBtmpToolBox
{
public static Form MainForm {get;set;}
public static int testStr2Int = MainForm.Str2Int("100");
}
and from the Form :
public partial class MyForm1 : Form
{
private override OnLoad(..){
base.OnLoad(...);
MyLoadedBtmpToolBox.MainForm =this;
}
}
This design is fragile by itself, as you has to gurantee that MyForm property is intialized before it's used to call ..testStr2Int = MainForm.Str2Int("100")...
So, considering that testStr2Int is public, may be intialization of it you can do in Form too and not in static class.