I have a class in C# with a template and static method similar to
class BClass<T>
{
public static BClass<T> Create()
{
return new BClass<T>();
}
}
From this I derive a class and specify a template parameter to the base class
class DClass : BClass<int> { }
A problem occurs when I try to use the static method to create an instance of D
class Program
{
static void Main(string[] args)
{
DClass d = DClass.Create();
}
}
Gives a compiler error "Cannot implicitly convert type 'Test.BClass<int> ' to 'Test.DClass'."
Adding the below cast leads to a runtime casting exception.
DClass d = (DClass)DClass.Create();
Is there any succint way to allow the static method to create instances of the derived class? Ideally I would like the equivalent of a c++ typedef and I don't want the below syntax (which does work).
BClass<int> d = DClass.Create();
It seems that what you want is for DClass to be an alias for BClass<int>. But that's not what you have here. What you have is that DClass derives from BClass<int>. Thus calling DClass.Create(); creates a BClass<int>, which is not a DClass (it's the other way around).
This might make it clearer. Suppose you had this hierarchy:
class Rectangle {
static Rectangle Create() {
return new Rectangle();
}
}
class Square : Rectangle { }
// code elsewhere
var shape = Square.Create(); // you might want this to return a square,
// but it's just going to return a rectangle
One option to get something like the functionality you want might be to define your Create method like this:
static TClass Create<TClass>() where TClass : BClass<T>, new() {
return new TClass();
}
// code elsewhere
var shape = DClass.Create<DClass>();
That's a bit messy, though (and also requires that you write a parameterless constructor for DClass). If you're dead set on using a Create method for the instantiation of your objects, consider writing a factory class for it.
Yes it is possible, by having a type reference to the type itself. Note that in the .NET world we are talking of generics, not templates, which do have important differences in the way they work.
class BClass<T, TSelf> where TSelf: BClass<T, TSelf>, new() {
public static TSelf Create() {
return new TSelf();
}
}
class DClass: BClass<int, DClass> {}
class Program {
static void Main(string[] args) {
DClass d = DClass.Create();
}
}
class BClass<T>
{
public static T1 Create<T1, T2>() where T1 : BClass<T2>, new()
{
return new T1();
}
}
class DClass : BClass<int> { }
class Program
{
static void Main(string[] args)
{
DClass d = DClass.Create<DClass, int>();
}
}
Related
Previously I've had a static TopUp() method what I wanted to substitute with the Baseclass's static constructor, because it's "performed once only" as the msdn states.
msdn: Static Constuctor
Any solution for keep the derived classes' initialization in the constructor and perform it only once?
class BaseClass<T>
{
static BaseClass()
{
for (byte i = 0; i < 2; i++)
{
var temp = new Junction<byte>[2] { new Level2<byte>(), new OtherLevel2<byte>() };
Program.myList.Add(temp);
}
Console.WriteLine("static BaseClass()");
}
}
abstract class Junction<T> : BaseClass<T> { }
sealed class Level2<T> : Junction<T> { }
sealed class OtherLevel2<T> : Junction<T> { }
class Program
{
internal static List<Junction<byte>[]> myList = new List<Junction<byte>[]>();
static Program()
{
BaseClass<object> callTheStaticMethod = new BaseClass<object>();
}
static void Main()
{
Console.WriteLine("myList.Count = " + myList.Count);
Console.ReadLine();
}
}
Output:
static BaseClass()
static BaseClass()
myList.Count = 4
Your static construction is called only once. Once per type, that is.
Each time you use your BaseClass<T> with a different type parameter, that's a completely different type. So, Junction<byte>, which inherits BaseClass<byte>, is a different type from BaseClass<object>. The static constructor for BaseClass<byte> is called, as well as the static constructor for BaseClass<object>.
It's not really clear from your question what it is you're actually trying to achieve. I will say, that the use of Junction<byte> in the static constructor strongly suggests that your class is not really generic at all. Any other use of BaseClass<T> is necessarily still dependent on Junction<byte>, and thus BaseClass<byte>. And this probably negates whatever benefit you thought you were going to get by making the class generic.
You can force the static constructor to execute only once by moving it to a non-generic base class inherited by BaseClass<T>. E.g.:
class BaseClass { /* static constructor here */ }
class BaseClass<T> : BaseClass { /* other stuff */ }
But given the lack of generic-ness in the class to start with, it's not clear that this will really help much. There seems to be a broader design flaw here that should be addressed.
The issue is that you have the static initializer in a typed base class. The issue is that BaseClass<string> and BaseClass<int> are considered two different types. The actual classes are generated at compile time, and so the compiler duplicates the static initializer for each variation.
If you change the last line in the static initializer to include the name of the type you'll be able to get a better idea of this issue.
In .Net 4.6 you can do this:
Console.WriteLine($"static BaseClass<{nameof(T)}>()");
In .Net 4.0 or later you can do this:
string typeName = typeof(T).FullName;
Console.WriteLine(string.Format("static BaseClass<{0}>()", typeName));
To resolve your issue, do your static initialization in a standard class that does not have a type parameter. In this case, you can simply remove the <T> type parameter from the BaseClass. Example:
class BaseClass
{
static BaseClass()
{
for (byte i = 0; i < 2; i++)
{
var temp = new Junction<byte>[2] { new Level2<byte>(), new OtherLevel2<byte>() };
Program.myList.Add(temp);
}
Console.WriteLine($"static BaseClass<{nameof(T)}>()");
}
}
abstract class Junction<T> : BaseClass { }
sealed class Level2<T> : Junction<T> { }
sealed class OtherLevel2<T> : Junction<T> { }
Suppose I have some relatively complex generic object that could be simplified as
class A<T>
{
static void foo(T x) { }
}
To use foo, one must repeatedly use the class name with the generic.
A<MyLongTypeNameIsNotFunToType>.foo(x);
It would be very nice if it was possible to simplify this:
alias AA = A<MyLongTypeNameIsNotFunToType>;
AA.foo(x);
Only thing I can think of is to create a wrapper class
class B : A<MyLongTypeNameIsNotFunToType> { }
which allows me to access A's static members through B. One problem is that this requires a public constructor, which, in my case, is not possible. Obviously I could wrap A's static members in B but that seems highly redundant.
[I tried using, but note that I need to access the static members so I need the static type. Using doesn't seem to work with static types.
error: ___ is a type which isn't valid in the given context]
Any elegant solution?
I have two solutions:
use using in the class file as all others have mentioned..
Class definition:
class A<T>
{
public static void foo(T x) { }
}
Usage:
using Alias = A<MyLongTypeNameIsNotFunToType>;
public class Dummy
{
public Dummy(MyLongTypeNameIsNotFunToType x)
{
Alias.foo(x);
}
}
Define the class A in different way such that type T is resolved implicitly meaning type of parameter x will resolve type T automatically (at compile-time).
My reason for going with this option will be that you have static method otherwise you can implement class A<T> same way as List<T> and use the solution 1 given above.
Class definition:
class A // <-- removed the <T> from class and added in the method declaration
{
public static void foo<T>(T x) { }
}
Usage:
public class Dummy
{
public Dummy(MyLongTypeNameIsNotFunToType x)
{
A.foo(x);
}
}
I hope you see the simplicity in the solution 2.
To make an alias of a Type you do the following where your namespaces are specified
using S = MyLongTypeNameIsNotFunToType;
Then to use it you can do the following
//A<S>.foo(new S());
A<S>.foo(x);
You can also continue to change A to the following
using S = MyLongTypeNameIsNotFunToType;
using AA = A<MyLongTypeNameIsNotFunToType>;
And then in your code you can go and do
AA.foo(x);
Or
A<S>.foo(x);
Here is a copy and paste into a console application sample
namespace ConsoleApplication3
{
using B = MyLongTypeNotFunToType;
using C = A<MyLongTypeNotFunToType>;
public class A<T>
{
public static void foo(T foo)
{
}
}
public class MyLongTypeNotFunToType
{
}
class Program
{
static void Main(string[] args)
{
var x = new B();
A<B>.foo(x);
C.foo(x);
}
}
}
Use using to alias your type or namespace.
using identifier = namespace-or-type-name;
So you can do this.
using LongType = A<MyLongTypeNameIsNotFunToType>;
You can read more about usage and details here
Update :
It would be very nice if it was possible to simplify this:
alias AA = A<MyLongTypeNameIsNotFunToType>;
AA.foo(x);
Yes, you can achieve this with below code.
using newname = A<int> ;
newname.foo(10);
Check the Demo
I want to force my child classes to pass themselves as as the generic parameter to the parent class.
For example :
class BaseClass<T> where T: BaseClass
{
//FullClassName : Tuple [Save,Update,Delete]
Dictionary<string,Tuple<delegate,delegate,delegate>> dict = new Dictionary...;
static BaseClass()
{
RegisterType();
}
private static void RegisterType()
{
Type t = typeof(T);
var props = t.GetProperties().Where(/* Read all properties with the SomeCustomAttribute */);
/* Create the delegates using expression trees and add the final tuple to the dictionary */
}
public virtual void Save()
{
delegate d = dict[t.GetType().FullName];
d.Item1(this);
}
}
class ChildClass : BaseClass<ChildClass>
{
[SomeCustomAttribute]
public int SomeID {get;set;}
[SomeCustomAttribute]
public string SomeName {get; set;}
}
public class Program
{
public static void Main(string[] args)
{
ChildClass c = new ChildClass();
c.Save();
}
}
Obviously the above code won't compile. I'll restate : I want the child class to pass itself as the generic parameter and not any other child of BaseClass.
(The above code is kind of a psuedo code and will still not compile).
You can do this:
public class BaseClass<T> where T: BaseClass<T> { }
public class ChildClass : BaseClass<ChildClass> { }
But this doesn't force you to use ChildClass as the generic parameter. You could do this public class OtherChildClass : BaseClass<ChildClass> { } which would break the "coontract" that you want to enforce.
The direct answer is that if your accessing a static method then typeof(T) will give you the type for reflection.
However, there is probably better solutions than using reflection. Options:
1) Static constructor on the child class.
2) Abstract method declared in the base class.
I do not know the application, but I get concerned about my design if I feel like using a static constructor, I also get concerned if a base class needs to initialize the child class.
I suggest looking at injection as a solution rather than inheritance. It offers superior unit testing and often a better architecture.
More info (after initial post), this is my preferred solution:
public interface IRegesterable
{
void Register();
}
public class Widget : IRegesterable
{
public void Register()
{
// do stuff
}
}
public class Class1
{
public Class1(IRegesterable widget)
{
widget.Register();
}
}
Hope this helps
The ConcurrentDictionary is being used as a Set<Type>. We can check in the Set<Type> if the type has been initialized. If not we run RegisterType on the type.
public abstract class BaseClass
{
//Concurrent Set does not exist.
private static ConcurrentDictionary<Type, bool> _registeredTypes
= new ConcurrentDictionary<Type, bool>();
protected BaseClass()
{
_registeredTypes.GetOrAdd(GetType(), RegisterType);
}
private static bool RegisterType(Type type)
{
//some code that will perform one time processing using reflections
//dummy return value
return true;
}
}
public class ChildClass : BaseClass
{
}
There are several inefficiencies with this pattern though.
object.GetType() is pretty darn slow, and inefficient.
Even with the HashSet behavior, we are checking for initialization on each instanciation. Its as fast as I can get it, but its still pretty superfluous.
i'm writing some ashx handlers which are wired to a mock service, and i want them to share the mock service instance. The simplest approach i though was creating a static instance
public class AbstractHandler
{
static IService _impl;
public static IService Impl
{
get
{
if (_impl == null)
{
_impl = new MockService();
}
return _impl;
}
}
}
However, i'm wondering if this is going to work at all; will different handlers that inherit from this class will have their own static _impl reference or they will be shared?
A static field exists once, except in the case of a generic type, in which case it exists once for each used combination of generic parameters.
Even if the class is a base class, possibly abstract, the same rules apply. Note that if the class in which the field is declared is not generic, the field will exist once, even if descendants are generic. The rule about "once per combination ..." only comes into play if the class that declares the static field is generic.
So, if your question instead had been:
How can I make the static field be per descendant and not just once
Then the answer would've been that you should make your base class generic, and pass the descendant type as the generic parameter.
Example LINQPad script to demonstrate the "once per generic parameter combination":
void Main()
{
var i = new Test<int>();
var s = new Test<string>();
Test<bool>.UsageCount.Dump();
Test<int>.UsageCount.Dump();
Test<string>.UsageCount.Dump();
}
public class Test<T>
{
public static int UsageCount;
public Test()
{
UsageCount++;
}
}
Output:
0
1
1
Example to demonstrate with base class:
void Main()
{
var i = new Test1();
var s = new Test2();
Test1.UsageCount.Dump();
Test2.UsageCount.Dump();
Test3.UsageCount.Dump();
}
public abstract class Base<T>
{
public static int UsageCount;
protected Base()
{
UsageCount++;
}
}
public class Test1 : Base<Test1>
{
}
public class Test2 : Base<Test2>
{
}
public class Test3 : Base<Test3>
{
}
Output:
1
1
0
Suppose I write a library with the following:
public class Bar { /* ... */ }
public class SomeWeirdClass<T>
where T : ???
{
public T BarMaker(Bar b)
{
// ... play with b
T t = (T)b
return (T) b;
}
}
Later, I expect users to use my library by defining their own types which are convertible to Bar and using the SomeWeirdClass 'factory'.
public class Foo
{
public static explicit operator Foo(Bar f)
{
return new Bar();
}
}
public class Demo
{
public static void demo()
{
Bar b = new Bar();
SomeWeirdClass<Foo> weird = new SomeWeirdClass<Foo>();
Foo f = weird.BarMaker(b);
}
}
this will compile if i set where T : Foo but the problem is that I don't know about Foo at the library's compile time, and I actually want something more like where T : some class that can be instantiated, given a Bar
Is this possible? From my limited knowledge it does not seem to be, but the ingenuity of the .NET framework and its users always surprises me...
This may or not be related to the idea of static interface methods - at least, I can see the value in being able to specify the presence of factory methods to create objects (similar to the same way that you can already perform where T : new())
edit: Solution - thanks to Nick and bzIm - For other readers I'll provide a completed solution as I understand it:
edit2: This solution requires Foo to expose a public default constructor. For an even stupider better solution that does not require this see the very bottom of this post.
public class Bar {}
public class SomeWeirdClass<T>
where T : IConvertibleFromBar<T>, new()
{
public T BarMaker(Bar b)
{
T t = new T();
t.Convert(b);
return t;
}
}
public interface IConvertibleFromBar<T>
{
T Convert(Bar b);
}
public class Foo : IConvertibleFromBar<Foo>
{
public static explicit operator Foo(Bar f)
{
return null;
}
public Foo Convert(Bar b)
{
return (Foo) b;
}
}
public class Demo
{
public static void demo()
{
Bar b = new Bar();
SomeWeirdClass<Foo> weird = new SomeWeirdClass<Foo>();
Foo f = weird.BarMaker(b);
}
}
edit2: Solution 2: Create a type convertor factory to use:
#region library defined code
public class Bar {}
public class SomeWeirdClass<T, TFactory>
where TFactory : IConvertorFactory<Bar, T>, new()
{
private static TFactory convertor = new TFactory();
public T BarMaker(Bar b)
{
return convertor.Convert(b);
}
}
public interface IConvertorFactory<TFrom, TTo>
{
TTo Convert(TFrom from);
}
#endregion
#region user defined code
public class BarToFooConvertor : IConvertorFactory<Bar, Foo>
{
public Foo Convert(Bar from)
{
return (Foo) from;
}
}
public class Foo
{
public Foo(int a) {}
public static explicit operator Foo(Bar f)
{
return null;
}
public Foo Convert(Bar b)
{
return (Foo) b;
}
}
#endregion
public class Demo
{
public static void demo()
{
Bar b = new Bar();
SomeWeirdClass<Foo, BarToFooConvertor> weird = new SomeWeirdClass<Foo, BarToFooConvertor>();
Foo f = weird.BarMaker(b);
}
}
Sounds like you found a solution to the larger problem. To answer your specific question: no, neither C# nor the CLR support the "backwards" generic type parameter constraint. That is,
class C<T> where Foo : T
"T must be Foo or a type which Foo converts to" is not supported.
There are languages that have that sort of constraint; IIRC Scala is such a language. I suspect this feature would be handy for certain uses of contravariant interfaces.
I don't think there is necessarily a syntactically cool way to do this built into the language. One possible solution to your problem could be to define a convertible interface:
public interface IConvertible<T>
where T : new() // Probably will need this
{
T Convert();
}
Then your class could be:
public class Foo : IConvertible<Bar>
{
}
I think this gets you close to where you want to be... All the Foo's and Bar's in your question sometimes make it hard to determine exactly what your intent is. Hope this helps.
Edit: Added where constraint... you will probably have to be able to create a new instance in your convertible class.
Edit 2: Made Foo inherit from ICovertible<Bar>
You could make a detour via an interface which is used as a type constraint.
For example, where T : IComparable<U> is used to constrain the type to something that can be compared to another thing, which must express this ability by implementing IComparable<another>. If you had an interface ICastableFrom<T>, you could achieve what you want by forcing them to implement ICastableFrom<Bar>.
Rather than go through the trouble of defining an interface and modifying your class to implement that interface, why not just do this?
public class SomeWeirdClass<T>
{
// aside: why is this method called 'BarMaker' if it returns a T?
public T BarMaker(Bar b, Func<Bar, T> converter)
{
// ... play with b
return converter(b);
}
}
Then in the event that you are dealing with an object of a type T to which Bar can be directly cast, this method could be called simply as follows:
var someWeirdObject = new SomeWeirdClass<Foo>();
var someBar = new Bar();
var someFoo = someWeirdObjcet.BarMaker(someBar, bar => bar as Foo);
By the way (since the Func<T, TResult> delegate emerged in .NET 3.5), you could also use Converter<TInput, TOutput> (which is exactly the same) for the converter parameter.