In C# I have a generic class:
public class MyGeneric<ParameterClass> where ParameterClass: MyGenericParameterClass, new() {
public static int Variable;
}
Now in C++ if I instantiated a templated class with different parameters each complete class would get it's own Variable, so I just can't say
MyGeneric.Variable = 1; // invalid in C++
in C++, but seems like I can do so in C#.
I'd like to clarify...
If I have a generic with a static member variable is that variable shared among all generic instantiations?
Section 25.1.4 of the ECMA C# Language specification
A static variable in a generic class declaration is shared amongst
all instances of the same closed constructed type (§26.5.2), but is
not shared amongst instances of different closed constructed types.
These rules apply regardless of whether the type of the static
variable involves any type parameters or not.
You may see this blog post: Static fields in generic classes by Gus Perez
You can't do that in C# as well.
MyGeneric.Variable = 1;
Consider the following example from ECMA Language Specification.
class C<V>
{
static int count = 0;
public C()
{
count++;
}
public static int Count
{
get { return count; }
}
}
class Application
{
static void Main()
{
C<int> x1 = new C<int>();
Console.WriteLine(C<int>.Count); // Prints 1
C<double> x2 = new C<double>();
Console.WriteLine(C<double>.Count); // Prints 1
Console.WriteLine(C<int>.Count); // Prints 1
C<int> x3 = new C<int>();
Console.WriteLine(C<int>.Count); // Prints 2
}
}
MyGeneric<MyClass>.Variable
MyGeneric<MyOther>.Variable
These two are different static variables treated like separate classes.
No, it is not. Generic types can be "open" or "closed." An open type is one like List<T> where the type parameter isn't defined; List<int> is a closed type.
Essentially, the open type isn't treated as a proper "Type" by the runtime - only the closed versions are true types. So, MyGeneric<int> and MyGeneric<string> are two entirely different types, and thus have their own instances of the static variable.
This is made more obvious by the fact that you can't call your static member in the way you suggest: MyGeneric.Variable will not compile in C#.
This console application code illustrates it quite simply:
class Program
{
static void Main(string[] args)
{
Test<int>.i = 2;
Test<string>.i = 8;
Console.WriteLine(Test<int>.i); // would write "8" if the fields were shared
Console.WriteLine(Test<string>.i);
// Console.WriteLine(Test.i); // does not compile
// Console.WriteLine(Test<>.i); // does not compile
}
}
class Test<T>
{
public static int i;
}
No, it is not shared.
Each MyGeneric<T> class will resolve to a different runtime type, for each possibility of T.
Please check that there is no non-generic MyGeneric class with the Variable static member.
As stated, the answer to your question is no. However, what you can do is use a parent class to your generic class, and have your static variable in there. Any method you need to call could be abstracted into that parent class.
abstract class MyBase
{
protected static MyBase selected;
public abstract void Deselect();
}
class MyGeneric<T> : MyBase
{
public void Select()
{
if (selected != null)
{
if (selected != this)
{
selected.Deselect();
}
}
selected = this;
//...
}
public override void Deselect()
{
//...
}
}
Related
When I run the following code I get RuntimeBinderException: 'object' does not contain a definition for 'SetIt'.
public interface IInput { }
public interface IThing<in TInput>
{
void SetIt(TInput value);
}
public class ThingMaker
{
private class Thing<TInput> : IThing<TInput>
where TInput : IInput
{
public void SetIt(TInput value){}
}
private class Input : IInput {}
public IThing<IInput> GetThing()
{
return new Thing<IInput>();
}
public IInput GetInput()
{
return new Input();
}
}
class Program
{
static void Main(string[] args)
{
var thingMaker = new ThingMaker();
var input = thingMaker.GetInput();
dynamic thing= thingMaker.GetThing();
thing.SetIt(input);
}
}
If I switch thing to a var it works fine. So clearly, thing has SetIt. How come this fails when I use dynamic? Shouldn't any thing that works as var also work when it is dynamic?
I think it has something to do with Thing<TInput> being a private inner class because it works when I make it public.
Here is a simpler example of your problem:
class A
{
class B
{
public void M() { }
}
public static object GetB() { return new B(); }
}
class Program
{
static void Main(string[] args)
{
dynamic o = A.GetB();
o.M();
}
}
The generics and interfaces are just a distraction.
The problem is that the type B (or in your case, Thing<IInput>) is a private class, and so at the call site, cannot resolve to that actual type. Recall that dynamic simply is an object variable but where compilation has been postponed until run-time. It isn't intended to let you do things at run-time you wouldn't otherwise be able to do, and "wouldn't otherwise be able to do" is judged based on the accessible type at the call site (which in this case, is object).
As far as the runtime binder is concerned, the type is simply object (hence the error message telling you that object doesn't contain the member you want).
Of course, it is theoretically possible that dynamic could have been implemented differently, and could do a more in-depth search for valid types it could treat the object as for the purpose of binding members to the object (i.e. implemented interfaces rather than just the object's actual type). But that's just not how it was implemented, and it would have been much more costly to do so (both in terms of the original design and implementation, and of course in terms of run-time cost of code that uses dynamic).
Related reading (arguably duplicates):
Is this a bug in dynamic?
Is this a hole in dynamic binding in C# 4?
I would like to create a function that returns new object according to the parameter, for example:
Base Class:
class BaseClass
{
public int x;
}
Class One:
class TestClassOne: BaseClass
{
public TestClassOne()
{
this.x = 1;
}
}
Class Two:
class TestClassTwo: BaseClass
{
public TestClassOne()
{
this.x = 2;
}
}
Main:
static void Main(string[] args)
{
BaseClass bc = GetConstructor("TestClassOne");
Console.WriteLine(bc.x); //Prints 1
}
static BaseClass GetConstructor(string className)
{
if(className.Equals("TestClassOne"))
{
return new TestClassOne();
}
else if(className.Equals("TestClassTwo"))
{
return new TestClassTwo();
}
return null;
}
The code I wrote works well, the problem is when I will have a lot of derived classes like TestClassThree, TestClassFour... TestClassThousand.
How can I make a function that returns the correct constructor without if else or switch case and etc?
I think that reflection would be a good option but I'm not really sure how to use it.
Thanks!
It would be best if you can use a generic method, lik in the answer of René, but you are using strings, so it doesn't seem so.
There are two steps:
Get the correct type;
Create an instance.
This is the minimal code necessary:
Type t = Assembly.GetExecutingAssembly().GetType("SO.BaseClass");
object o = Activator.CreateInstance(t);
As you can see, you need to know the assembly and the namespace of the type, or you will have to do some fuzzy matching on either.
I would offer a word of caution with your implementation. What you are attempting to do is called a factory. Considering the fact that you are adding a dependency for a base class, you will be limited to only allowing constructors with that base class. If you ever needed certain classes to have a different base class but be offered through the same method, you would need to share an interface instead. Like others have suggested, you can use generics. Here is an example without generics:
public static IMyInterface GetMatchingClass(string className)
{
Type t = Type.GetType(className);
return (IMyInterface)Activator.CreateInstance(t);
}
As long as the classes you return implement the given interface, all is peachy.
In a non-static method I could use this.GetType() and it would return the Type. How can I get the same Type in a static method? Of course, I can't just write typeof(ThisTypeName) because ThisTypeName is known only in runtime. Thanks!
If you're looking for a 1 liner that is equivalent to this.GetType() for static methods, try the following.
Type t = MethodBase.GetCurrentMethod().DeclaringType
Although this is likely much more expensive than just using typeof(TheTypeName).
There's something that the other answers haven't quite clarified, and which is relevant to your idea of the type only being available at execution time.
If you use a derived type to execute a static member, the real type name is omitted in the binary. So for example, compile this code:
UnicodeEncoding.GetEncoding(0);
Now use ildasm on it... you'll see that the call is emitted like this:
IL_0002: call class [mscorlib]System.Text.Encoding
[mscorlib]System.Text.Encoding::GetEncoding(int32)
The compiler has resolved the call to Encoding.GetEncoding - there's no trace of UnicodeEncoding left. That makes your idea of "the current type" nonsensical, I'm afraid.
Another solution is to use a selfreferecing type
//My base class
//I add a type to my base class use that in the
//static method to check the type of the caller.
public class Parent<TSelfReferenceType>
{
public static Type GetType()
{
return typeof(TSelfReferenceType);
}
}
Then in the class that inherits it, I make a self referencing type:
public class Child: Parent<Child>
{
}
Now the call type typeof(TSelfReferenceType) inside Parent will get and return the Type of the caller without the need of an instance.
Child.GetType();
You can't use this in a static method, so that's not possible directly. However, if you need the type of some object, just call GetType on it and make the this instance a parameter that you have to pass, e.g.:
public class Car {
public static void Drive(Car c) {
Console.WriteLine("Driving a {0}", c.GetType());
}
}
This seems like a poor design, though. Are you sure that you really need to get the type of the instance itself inside of its own static method? That seems a little bizarre. Why not just use an instance method?
public class Car {
public void Drive() { // Remove parameter; doesn't need to be static.
Console.WriteLine("Driving a {0}", this.GetType());
}
}
I don't understand why you cannot use typeof(ThisTypeName). If this is a non-generic type, then this should work:
class Foo {
static void Method1 () {
Type t = typeof (Foo); // Can just hard code this
}
}
If it's a generic type, then:
class Foo<T> {
static void Method1 () {
Type t = typeof (Foo<T>);
}
}
Am I missing something obvious here?
When your member is static, you will always know what type it is part of at runtime. In this case:
class A
{
public static int GetInt(){}
}
class B : A {}
You cannot call (edit: apparently, you can, see comment below, but you would still be calling into A):
B.GetInt();
because the member is static, it does not play part in inheritance scenarios. Ergo, you always know that the type is A.
For my purposes, I like #T-moty's idea. Even though I have used "self-referencing type" information for years, referencing the base class is harder to do later.
For example (using #Rob Leclerc example from above):
public class ChildA: Parent<ChildA>
{
}
public class ChildB: Parent<ChildB>
{
}
Working with this pattern can be challenging, for example; how do you return the base class from a function call?
public Parent<???> GetParent() {}
Or when type casting?
var c = (Parent<???>) GetSomeParent();
So, I try to avoid it when I can, and use it when I must. If you must, I would suggest that you follow this pattern:
class BaseClass
{
// All non-derived class methods goes here...
// For example:
public int Id { get; private set; }
public string Name { get; private set; }
public void Run() {}
}
class BaseClass<TSelfReferenceType> : BaseClass
{
// All derived class methods goes here...
// For example:
public TSelfReferenceType Foo() {}
public void Bar(TSelfRefenceType obj) {}
}
Now you can (more) easily work with the BaseClass. However, there are times, like my current situation, where exposing the derived class, from within the base class, isn't needed and using #M-moty's suggestion just might be the right approach.
However, using #M-moty's code only works as long as the base class doesn't contain any instance constructors in the call stack. Unfortunately my base classes do use instance constructors.
Therefore, here's my extension method that take into account base class 'instance' constructors:
public static class TypeExtensions
{
public static Type GetDrivedType(this Type type, int maxSearchDepth = 10)
{
if (maxSearchDepth < 0)
throw new ArgumentOutOfRangeException(nameof(maxSearchDepth), "Must be greater than 0.");
const int skipFrames = 2; // Skip the call to self, skip the call to the static Ctor.
var stack = new StackTrace();
var maxCount = Math.Min(maxSearchDepth + skipFrames + 1, stack.FrameCount);
var frame = skipFrames;
// Skip all the base class 'instance' ctor calls.
//
while (frame < maxCount)
{
var method = stack.GetFrame(frame).GetMethod();
var declaringType = method.DeclaringType;
if (type.IsAssignableFrom(declaringType))
return declaringType;
frame++;
}
return null;
}
}
EDIT
This methods will works only when you deploy PDB files with the executable/library, as markmnl pointed out to me.
Otherwise will be a huge issue to be detected: works well in developement, but maybe not in production.
Utility method, simply call the method when you need, from every place of your code:
public static Type GetType()
{
var stack = new System.Diagnostics.StackTrace();
if (stack.FrameCount < 2)
return null;
return (stack.GetFrame(1).GetMethod() as System.Reflection.MethodInfo).DeclaringType;
}
Below is a quick example of what I am doing. Basically, I have multiple interfaces that can be implemented by 1 class or by separate classes, so I store each one in the application. My only question is about the variables myInterface, yourInterface, and ourInterface. Do they reference the same object or are there 3 different objects?
interface IMyInterface
{
void MyFunction();
}
interface IYourInterface()
{
void YourFunction();
}
interface IOurInterface()
{
void OurFunction();
}
public class MainImplementation : IMyInterface, IYourInterface, IOurInterface
{
public void MyFunction() { }
public void YourFunction() { }
public void OurFunction() { }
}
private IMyInterface myInterface;
private IYourInterface yourInterface;
private IOurInterface ourInterface;
static void Main(string[] args)
{
myInterface = new MainImplementation() as IMyInterface;
yourInterface = myInterface as IYourInterface;
ourInterface = myInterface as IOurInterface;
}
Bonus: Is there a better way to do this?
They all reference the same object. So changes to them in the form of:
ourInterface.X = ...
Will be reflected in 'all views'.
Effectively what you are doing with your casting (and I presume you meant your last one to be 'as IOurInterface') is giving a different 'view' of the data. In this case, each interface opens up one function each.
They reference the same instance. There is only one instance.
1 new = 1 object. They all reference the same instance.
They reference the same object. Casting an object to a different just tells the compiler that when a method is called on this object, use the method defined in this class as opposed to a different one.
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.