public static (const) in a generic .NET class - c#

Is there a syntax trick to get to the constant in a generic class without specifying an (ad-hoc) type?
public class MyClass<T>{
public const string MyConstant = "fortytwo";
}
// I try to avoid this type specification.
var doeswork = MyClass<object>.MyConstant;
// Syntax similar to what I'd like to accomplish.
var doesnotwork = MyClass.MyConstant;
There is a caveat about the static variable (constant) not being shared between different types like MyClass<object> and MyClass<int> but my question is about possible available syntax trick.

Use a non-generic abstract parent class.
public abstract class MyClass
{
public const string MyConstant = "fortytwo";
}
public class MyClass<T> : MyClass
{
// stuff
}
var doeswork = MyClass.MyConstant;
That of course assumes that there's some reason the constant needs to be part of the generic class; if it has public accessibility, I'm not seeing a reason why you wouldn't just put it in a separate class.
Having a non-generic abstract parent class is a good idea for every generic class you make; the generic class is actually a template for the specific subtype classes, rather than a true parent, so having a true non-generic parent can make some techniques (such as, but certainly not limited to, this one) a lot easier.

Something like this works:
using System;
namespace Demo
{
public class MyClass // Use a non-generic base class for the non-generic bits.
{
public const string MyConstant = "fortytwo";
public static string MyString()
{
return MyConstant;
}
}
public class MyClass<T>: MyClass // Derive the generic class
{ // from the non-generic one.
public void Test(T item)
{
Console.WriteLine(MyConstant);
Console.WriteLine(item);
}
}
public static class Program
{
private static void Main()
{
Console.WriteLine(MyClass.MyConstant);
Console.WriteLine(MyClass.MyString());
}
}
}
This approach works for any static types or values that you want to provide which do not depend on the type parameter. It also works with static methods too.
(Note: If you don't want anybody to instantiate the base class, make it abstract.)

Related

Subclassing and generics in C#

I want to subclass a large number of classes so that they will all contain a certain set of the same properties. What would be the right way to do it in order to avoid repetition? I thought of using generics like:
public class SuperT<T> : T
{
//the same set of properties
}
But the compiler says
Cannot derive from 'T' because it is a type parameter
EDIT: I am trying to subclass some classes in a third party assembly so I cannot use a base class.
For example, the types are "Image", "Label", "Button" etc and I want to subclass them all to contain a property like "Radius". (So that I would use SuperImage element in XAML and when I set it's Radius property from XAML, I will be able to run some certain logic.)
One other way I just thought of right now is using T4 templates. I wonder if there is a way to do this with generics without resorting to templates? I cannot understand why the compiler rejects it.
If these classes all share a common base class or common interface you could write an extension method.
public static class ShapeExetnsionsExtLib
{
public static double Radius(this ShapeBase shape){
return /*calculate radious*/;
}
}
From comments
I am trying to subclass some classes in a third party assembly so I cannot use a base class.
For example, the the types are "Image", "Label", "Button" etc and I want to subclass them all to contain a property like "radius".
Yes they share common base classes but I cannot add anything new to them.
I don't think generics have anything to do with this, however inheritance is probably what you're looking for.
There are two types of inheritance that you can use to subclass, and extension methods work to "superclass"... sort of.
Is-A inheritance
Has-A inheritance
And to simply add a similar method to a bunch of third party objects, you'll use an extension method.
Is-A inheritance
Use a base class if you've got similar method implementations.
public abstract class BaseFoo {
public void Bar() {
// actual code
}
}
public class Foo : BaseFoo
{
}
var foo = new Foo();
foo.Bar();
Use an Interface if you need to implement the same method on each class.
public interface IFoo {
void Bar();
}
public class Foo : IFoo {
public override void Bar(){
// bar implementation
}
}
var foo = new Foo();
foo.Bar();
Combining the two is also allowed, but you can only inherit on base class, where you can inherit multiple interfaces.
Has-A inheritance
This is particularly useful with dependency injection, but it's simply the notion that you have an instance of another class to work with. It's essentially a wrapper class for you to work with.
public class Foo {
private readonly ThirdPartyFoo _tpFoo;
void Foo(ThirdPartyFoo tpFoo) {
_tpFoo = tpFoo;
}
public void Bar(){
// now I can do something with _tpFoo;
_tpFoo.Bar();
}
}
var tpFoo = new ThirdPartyFoo();
var foo = new Foo(tpFoo);
foo.Bar(); // invokes the underlying tpFoo
Lastly, if you just need to add a method to existing classes, then you create an extension method.
public static class ViewExtensions()
{
// this assumes your Image, Button, Label all inherit from View.
public static Whatever Radius(this View view) {
// do your radius work.
}
}
Just Use a base class:
public class Base
{
public int Id { get; set; }
public string Name { get; set; }
}
And inherite from it:
public class A : Base
{
}
public class B : Base
{
}
In general, you want to use one of the answers already posted about using a base class and inheriting from that. However, if the classes are in a third party library and are marked as sealed, then you will need to create a wrapper class to use as a base class.
(Note that this option is a workaround and doesn't truly inherit from the third party class, so things in that class that are marked as protected won't be accessible without a liberal use of reflection.)
// The sealed class within another library
public sealed ThirdPartyClass
{
public ThirdPartyClass(int i) { }
public int SomeProperty { get; set; }
public int SomeMethod(string val) { return 0; }
public static void SomeStaticMethod() { }
}
// The wrapper class to use as a pseudo base class for ThirdPartyClass
public class BaseClass
{
private ThirdPartyClass _obj;
public BaseClass(int i) { _obj = new ThirdPartyClass(i); }
public int SomeProperty
{
get { return _obj.SomeProperty; }
set { _obj.SomeProperty = value; }
}
public int SomeMethod(string val) { return _obj.SomeMethod(val); }
public static SomeStaticMethod() { ThirdPartyClass.SomeStaticMethod(); }
}
// The child class that inherits from the "base" BaseClass
public class ChildClass : BaseClass
{
}
First of all, this might be a logical problem. What if you are going to extend a sealed class? Or Int32 class? Delegate?
Anyway, the way I recommend is to create an interface and implement all the functions you need in the subclass.

Using structs with generics - Inconsistent accessibility

I'm trying to use generics in inheritance with structs, see.
public class AuditLogEntry : ObjectBase<AuditLogEntry.AuditLogEntryStruct>
{
private struct AuditLogEntryStruct
{
public int AuditID;
}
}
public abstract class ObjectBase<T>
{
}
It won't let me use private for my struct, as it throws the error:
Inconsistent accessibility: base class 'ObjectBaseAuditLogEntry.AuditLogEntryStruct>' is less accessible than class 'AuditLogEntry'.
However I don't really want to make my struct public.
Any ideas?
Thanks,
Alex
Follow on question:
Here is what we are trying to do:
class AuditLogEntry : ObjectBase<AuditLogEntry.AuditLogEntryStruct>
{
internal struct AuditLogEntryStruct
{
public int AuditID;
}
public int AuditID
{
get
{
return udtObject.AuditID;
}
set{
BeginEdit();
udtObject.AuditID = value;
}
}
class ObjectBase<T>
{
protected T udtObject;
protected T udtPreEditObject;
protected void BeginEdit()
{
if (!IsDirty)
{
IsDirty = true;
udtPreEditObject = udtObject;
}
}
}
I'm not sure how to achive this within making AuditLogEntryStruct public?
Thanks,
Alex
You can't derive a public class from a generic class when one or more of the type arguments aren't public
The types that any type derives from has to be as accessible as the deriving class, inculding any type parameters given as type arguments to the base class
if you have
public class publicClass{}
Any class can derive from A however if you changed it to
internal class internalClass{}
only other internal classes can derive from it.
The same is true if you passed either of the types as a type parameter. The first three below are valid the fourth is not
public class A : List<publicClass>{}
internal class B : List<internalClass>{}
internal class C : List<publicClass>{}
//not valid because D has wider accessibility than the close generic type List<internalClass>
public class D : List<internalClass>{}
EDIT
The language team at some point have had to make a decision whether to make a declaration as yours invalid or make any use of your type that resulted in illegal access to an inaccessible type invalid. In your case there would be several methods returning a type that would be inaccessible to all others than your class and a number of methods taking an argument of a type no other class could provide. So the only objects that would actually be able to use objects of your class would be objects of your class. You can solve that with composition instead of inheritance
public class AuditLogEntry
{
private ObjectBase<AuditLogEntry.AuditLogEntryStruct> _entry;
private struct AuditLogEntryStruct
{
public int AuditID;
}
}
public abstract class ObjectBase<T>
{
}
Consider this example:
public class Foo : List<Bar>
{
private struct Bar { }
}
var myFoo = new Foo();
...
var x = myFoo()[0]; // expression on the right side is of type Bar, yet Bar is inaccessible
UPDATE
What you are trying to achieve doesn't really require generics. You only access your structs inside ObjectBase<T> as if they were objects. You might as well change them to object and remove generic type altogether.
If you have some more logic that requires some sort of functionality from AuditLogEntryStruct to be accessable in ObjectBase<T>, you may extract an interface:
public interface IStructsWithSomeFunctionality { ... }
make your struct implement it and use it as your type parameter
public class AuditLogEntry : ObjectBase<IStructsWithSomeFunctionality> { ... }

C# Retrieving Classname in a static method

Example:
namespace MyProgram.Testing
{
public class Test1
{
public void TestMethod()
{
String actualType = this.GetType().FullName.ToString();
return;
}
public static String GetInheritedClassName()
{
return System.Reflection.MethodBase.GetCurrentMethod().ReflectedType.FullName;
}
}
public class Test2 : Test1
{
}
public class Test3
{
String test2ClassName = Test2.GetInheritedClassName();
}
}
Anyway, I want it to return "MyProgram.Testing.Test2" but instead Test2.GetInheritedClassName() returns "MyProgram.Testing.Test1". What do I have to put into that static class to get it to return that (if possible)?
It's not possible. When you call Test2.GetInheritedClassName, it's actually Test1.GetInheritedClassName that is called, because Test2.GetInheritedClassName doesn't really exists (btw, some tools like Resharper would show a warning: Access to a static member of a type via a derived type)
Static members don't participate in inheritance, which is kind of logical since inheritance only makes sense when you're dealing with instances...
The code that's printing out the type is the base-class method. Except for rare Reflection scenarios such as you provide above, execution wouldn't be affected by whether the method is called using the derived type or the base type, so the system makes no distinction.
You could, however, get around this by defining a generic base type:
class ClassNameTesterBase<T>where T:ClassNameTester<T>
{
public static String getName() { return (typeof(T)).Name; }
}
and then defining the other types of interest:
class ClassNameTester1<T&gt : ClassNameTesterBase<T> ...
class ClassNameTester2<T&gt : ClassNameTester1<T> ...
One may then if desired define leaf classes:
class ClassNameTester1 : ClassNameTester1<ClassNameTester1> { }
class ClassNameTester2 : ClassNameTester2<ClassNameTester2> { }
One slight caveat here is that ClassNameTester2 derives its innards from from ClassNameTester1<T> but is not substitutable for anything having to do with the ClassNameTester1<ClassNameTester1>; if it's being used as a static class, though, that shouldn't be a problem.

How to store a reference to a static class?

So something like:
public static class StaticClass {}
public class InstanceClass
{
static StaticClass StaticProperty {get;set;}
public InstanceClass()
{
InstanceClass.StaticProperty = StaticClass;
}
}
I thought one could do this but the compiler returns these errors:
static types cannot be used as parameters
static types cannot be used as return types
EDIT: I know that this doesn't work, but why? I imagine StaticClass is stored somewhere in memory, so other variables could be allowed to refer to it at the same memory, right?
EDIT2: One of the use cases would be something like this:
Say you have 5 different static classes you have collected with no source code, and they do generic stuff, so you want to have convenient access to them through a single static class. You could do it like:
public static class GenericStuff
{
public LinearAlgebra LinearAlgebra {get;set;}
public StringUtilities String {get;set;}
public GeometryOps Geometry {get;set;}
}
And use it like:
GenericStuff.LinearAlgebra.GetAngleBetweenVectors(v0, v1);
Some other use cases you could think of.
Update: I am going to use my psychic powers to try and figure what I think you're trying to do.
I'm guessing you have a static class with some methods that you want to access from within another class. Is that right?
Something like this, in other words:
static class HelperMethods
{
public static void SomeHelperMethod();
}
...and what you want to do is something like this?
class SomeOtherClass
{
public void MethodThatUsesHelperMethod()
{
// You want to be able to have "Helper" mean "HelperMethods"?
Helper.SomeHelperMethod();
}
}
If I've interpreted you correctly, there's only one way (that I can think) to sort of accomplish what you're after. This would be to add a using declaration to effectively alias your static type:
// At top of file
using Helper = HelperMethods;
Note that if you do this, you're creating a file-wide alias. There's no way to alias classes at only the class level.
StaticClass is the name of the class. Your StaticProperty property expects an instance of the class, which will never exist because the class is static.
I'm actually surprised you can even have a property typed as a static class, since it represents a total impossibility. (Oh wait, you can't do that; that's what you were saying.)
You say you want to store a "reference to a static class"; I have to assume you mean that you want a reference to the Type object representing the class, in which case you should do this:
public Type StaticProperty { get; set; }
// ...
StaticProperty = typeof(StaticClass);
Static classes are both abstract and sealed (take a peek at the generated IL). So, you can't create an instance of it, and you can't subclass it to have instances of subclasses. That combination alone makes it impossible for you to ever have a reference to an instance of a static class.
Now, to have a reference to the static class work the way you want, you'd have to have metaclasses in C#, or some different kind of aliasing.
To achieve what you want today, you'd have to manually delegate all methods from a wrapper class to the desired static class, or abandon static typing and use dynamic:
public class StaticWrapper : DynamicObject {
Type _type;
public StaticWrapper(Type type) {
_type = type;
}
public override bool TryInvokeMember(InvokeMemberBinder binder, object[] args, out object result) {
var method = _type.GetMethod(binder.Name, BindingFlags.Static | BindingFlags.Public, null, args.Select(a => a.GetType()).ToArray(), null);
if (method == null) return base.TryInvokeMember(binder, args, out result);
result = method.Invoke(null, args);
return true;
}
// also do properties ...
}
Usage:
public static class GenericStuff {
public readonly dynamic LinearAlgebra = new StaticWrapper(typeof(LinearAlgebra));
public readonly dynamic String = new StaticWrapper(typeof(StringUtilities));
public readonly dynamic Geometry = new StaticWrapper(typeof(GeometryOps));
}
Section ยง8.7.12 of the C# specification reads:
Classes that are not intended to be
instantiated, and which contain only
static members should be declared as
static classes. Examples of such
classes are System.Console and
System.Environment. Static classes
are implicitly sealed and have no
instance constructors. Static classes
can be used only with the typeof
operator and to access elements of the
class. In particular, a static class
cannot be used as the type of a
variable or be used as a type argument
Because a static class has no constructors, you can't instantiate it. Because it is sealed you cannot subclass it and create an instance of a subclass. Even if you could subclass it you wouldn't be able to call the base constructor, and therefore you still couldn't instantiate it.
Since you cannot create an object of the type of a static class, it makes no sense to use it as a return type.
Since StaticClass is a type name, not an expression, you cannot pass it as a parameter (in your case, to the property setter). However, you can obtain an instance of the Type class that represents it with the expression typeof(StaticClass).
You cannot store a reference to a static class. You can only store references to instances, and there are no instances of static classes (although static classes may have instance members).
You should take another look at the MSDN page on static classes.
"A static class is basically the same as a non-static class, but there is one difference: a static class cannot be instantiated. In other words, you cannot use the new keyword to create a variable of the class type. Because there is no instance variable, you access the members of a static class by using the class name itself."
I think this is what you are trying to say:
Ok, if you don't want to instantiate it, then your C# needs a bit more tweaking. Assuming your static class implements a property and/or method
public static class StaticClass
{
public static string StaticProperty {get; private set; }
public static void StaticMethod() { //DoSomething }
}
You can forward the property and function definitions in the InstanceClass, notice that you must prefix the class name of the static to the methods/properties that you want to call.
public class InstanceClass
{
private string StaticProperty
{
get { return StaticClass.StaticProperty; }
}
private StaticMethod()
{
StaticClass.StaticMethod();
}
public InstanceClass()
{ }
}
I think that using InstanceClass as a wrapper like this is a bit complicated, and unecessary. I've found that its worth trying to minimize the need for static classes and methods in a codebase. They cause all sorts of headaches when trying to test and debug.
I believe using the namespace feature would be the best way to accomplish what you're trying to do.
LinearAlgebra.cs
namespace GenericStuff
{
public static class LinearAlgebra
{
public static TypeOfResult Function() { ... }
}
}
Strings.cs
namespace GenericStuff
{
public static class Strings
{
public static TypeOfResult Function() { ... }
}
}
Geometry.cs
namespace GenericStuff
{
public static class Geometry
{
public static TypeOfResult Function() { ... }
}
}
All of which can be invoked starting with GenericStuff
var s = GenericStuff.Strings.Random(7);
var identity = GenericStuff.LinearAlgebra.Identity(3);
var square = GenericStuff.Geometry.Square(5);
var area = square.Area();
You can't do this. A class is not an instance of itself. "Dog" is not a Dog. You could assign typeof(StaticClass) to a field of type Type:
static StaticClass StaticProperty {get; set}
InstanceClass.StaticProperty = typeof(StaticClass);
This lets you use reflection on the type.
What I believe the op wants is a way to access other classes easily via a "proxy" that you know of.
So, lets say you have a class called MapHelpers:
public class MapHelper
{
public static string CalculateNearLocation (Vector3 position){...}
}
And you have many other "Helpers" that you don't really remember and just want to have them easily accessible. And so, you want to "store" them inside your "Helpers" class, just so you can remember where you put them.
You can either do this :
public class Helpers
{
public class MapHelpers : MapHelper{}
}
And be able to access your MapHelper via :
Helpers.MapHelpers.CalculateNearLocation(pos)
Or do this :
public partial class Helpers
{
}
public partial class Helpers
{
public class MapHelper
{
public static string CalculateNearLocation (Vector3 position){...}
}
}
And be able to access it via :
Helpers.MapHelper.CalculateNearLocation(pos)
However, the first method, will give you a warning on your IDE (if you have that set) about accessing static methods via derived type.
Depends on what you want to achieve in the end.
If you want to just change one class but not on runtime but on compile time (i.e. the same version of static file is going to be used), then you can easily just configure your app or just make several versions of the same file with various implementations.
Such approach is useful for e.g. translations if you have them in a static files.

generic inheritance in C#? [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Why cannot C# generics derive from one of the generic type parameters like they can in C++ templates?
I can do
public class MyGenericClass : DL
//but i cannot do
public class MyGenericClass <T> : T
How would i do the second? if i cannot do that, how can i do something like
public class MyGenericClass <T>
{
T obj;
//have all MyGenericClass.XYZ call obj.XYZ
}
This is not possible, because depending on what type T is, the public interface of MyGenericClass would change.
If you have lots of different classes that all expose the same interface, you could declare MyGenericClass to expose that interface, and in the implementation of all of the functions delegate the calls to obj
The specific question, why can't you do this:
public class MyGenericClass<T> : T
And you can do this:
public class MyGenericClass<T>
{
T obj;
}
The reason is that the CLR likes to be able to compile a single version of the code for MyGenericClass that will work for any reference type specified for T.
It can do this for the second case, because it can quietly replace T with object and insert appropriate casts, roughly equivalent to:
public class MyGenericClass
{
object obj;
}
But for the inheritance version, that trick doesn't work.
Also, many useful facilities would be impossible to describe through interface constraints. When you inherit from a type, you can do a lot more than just call methods on it - you can override them as well. Consider this hypothetical example:
class MyBase
{
public virtual void MyVirtual() { }
}
class MyGenericDerived<T> : T
{
public override void MyVirtual()
{
Console.WriteLine("Overridden!");
}
}
MyBase obj = new MyGenericDerived<MyBase>();
obj.MyVirtual();
What I want to do there is something like a "mix-in", where MyGenericDerived supplies definitions for virtual functions in whatever base it is applied to. But how does the compiler know that T will have a method called MyVirtual that can be overridden? I'd need to put a constraint on T. How would I express that through interfaces? It's impossible. Using interfaces to describe constraints isn't an adequate solution once you allow inheritance from type parameters. So that's another reason why it doesn't exist in the language today.
You could do something like
public interface IXyzable { void xyz(); }
public class MyGenericClass<T> : IXyzable where T : IXyzable {
T obj;
public void xyz() {
obj.xyz();
}
}
Edit: Now I understand the question
You'll need all your possible T's to implement some interface so that you know that obj.XYZ() makes sense, then you can do
public interface Ixyz
{
void XYZ();
}
public class MyGenericClass<T> : Ixyz where T:Ixyz, new()
{
T obj;
public MyGenericClass()
{
obj = new T();
}
public void XYZ()
{
obj.XYZ();
}
}
I've made MyGenericClass implement Ixyz too since it obviously does expose the right method, but maybe that's best left out since it allows
var x = new MyGenericClass<MyGenericClass<SomeClass>>();
which is unlikely to ever be a good idea.
This is pretty much duck-typing, but you could use reflection.
When you create the generic class with a reference to the obj, use reflection to try and find a method with the right signature. As long as you store a reference to the method, performance won't be too bad.
class BaseGeneric<T>
{
private T obj;
private MethodInfo mi;
private const string MethodNameOfInterest = "Xyz";
public BaseGeneric(T theObject)
{
this.obj = theObject;
Type t = obj.GetType();
mi = t.GetMethod(MethodNameOfInterest);
}
public void Xyz()
{
mi.Invoke(obj, null);
}
}
Of course, you would need to add a lot more for error checking and such, but that is the gist of what you could do. Also, don't forget to add the System.Reflection namespace to your using clause.
The .NET type system won't allow type declarations of the form you're attempting. One reason why this is disallowed should be intuitive: how would MyGenericClass<T> act when T is a sealed class (e.g. System.String)?
If you absolutely need this functionality (and you know that the type T you'll be using isn't sealed), you can generate proxies at runtime using the classes in the Reflection.Emit namespace. It may also be possible to achieve this effect using AOP tools like PostSharp.
What about this:
class BaseClass<T>
{
public T property { get; set; }
}
class GenericClass<T> : BaseClass<T>
{
}
class Program
{
static void Main(string[] args)
{
GenericClass<int> l = new GenericClass<int>();
l.property = 10;
}
}
This achieves what you want to do?

Categories