Why does C# not allow generic properties? - c#

I was wondering why I can not have generic property in non-generic class the way I can have generic methods. I.e.:
public interface TestClass
{
IEnumerable<T> GetAllBy<T>(); //this works
IEnumerable<T> All<T> { get; } //this does not work
}
I read #Jon Skeet's answer, but it's just a statement, which most probably is somewhere in the specifications.
My question is why actually it is that way? Was kind of problems were avoided with this limitation?

Technically, the CLR supports only generic types and methods, not properties, so the question is why it wasn’t added to the CLR. The answer to that is probably simply “it wasn’t deemed to bring enough benefit to be worth the costs”.
But more fundamentally, it was deemed to bring no benefit because it doesn’t make sense semantically to have a property parameterised by a type. A Car class might have a Weight property, but it makes no sense to have a Weight<Fruit> and a Weight<Giraffe> property.

This Generic Properties blog post from Julian Bucknall is a pretty good explanation. Essentially it's a heap allocation problem.

My guess is that it has some nasty corner cases that make the grammar ambiguous. Off-hand, this seems like it might be tricky:
foo.Bar<Baz>=3;
Should that be parsed as:
foo.Bar<Baz> = 3;
Or:
foo.Bar < Baz >= 3;

I think not using an automatic getter/setter illustrates why this isn't possible without having "T" defined at the class level.
Try coding it, the natural thing to do would be this:
IEnumerable<T> _all;
IEnumerable<T> All
{
get { return _all; }
}
Because your field uses "T", then "T" needs to be on the class the CLR knows what "T" is.
When you're using a method, you can delay definition of "T" until you actually call the method. But with the field/property, "T" needs to be declared in one place, at the class level.
Once you declare T on the class, creating a property becomes pretty easy.
public class TestClass<T>
{
IEnumerable<T> All { get; }
}
usage:
var myTestClass = new TestClass<string>();
var stuff = myTestClass.All;
And just like the "T" type parameter on a method, you can wait until you actually instantiate your TestClass to define what "T" will be.

I made somthing like that.
It type checks at run time.
public class DataPackage
{
private dynamic _list;
public List<T> GetList<T>()
{
return (List<T>)_list;
}
public void SetList<T>(List<T> list)
{
_list = list;
}
public string Name { get; set; }
}

Related

How could I declare list of generics with different and unknown types and How could I initialize a generic with a type only known at runtime?

This is a 2 part question.
Firstly
I have a class called ComponentList that looks like this:
public class ComponentList<T> : List<T> where T : Component
{
}
Now I want to create an empty list of typeless ComponentLists:
List<ComponentList<>> MasterList = new List<ComponentList<>>();
I get an error because the ComponentList wants a generic type specified even though I'm not trying to initialize any ComponentLists yet (just the MasterList that contains them). How would I declare the MasterList of ComponentLists without initializing any ComponentLists (as I plan to initialize them during runtime with types only known at runtime)? After all, the MasterList needs to contain ComponentLists of different generic types, not just one.
Secondly
I know this one has been asked before, but I can't seem to wrap my head around the concepts of any of the proposed solutions.
As you know, I have a List<> called MasterList which is a list of ComponentLists (a custom class). A ComponentList is a generic class of an undefined type (that is constrained to being a subtype of Component).
In the following example, I'm trying to check if a ComponentList generic type (referenced from MasterList) is the same as this class (the class the code's being called from).
if (MasterList[i].GetType() == typeof(ComponentList<this.GetType()>))
{
}
Problem is, the code is meant to be automatically called from unknown child classes, not from this parent class. So the ComponentList generic type needs to be compared with the type of the child class, not this base class. Hence the "this.GetType" inplace of what would be the hardcoded name of the actual base class.
The this.GetType() type passed in the ComponentList<> returns a "type expected" error apparently because GetType() returns compile time type, not runtime type (which is what I need).
So how could I get the runtime type? And if I can't, what would be the best alternative to accomplishing what I'm trying to do? (I've heard a bit about something called reflections that might help me but I really don't understand).
You cannot determine generic types at runtime. C# (all .Net, actually) is designed that way on purpose. The compiler treats a generic type virtually same way as an explicitly defined type.
Consider the following:
class MyGenericClass<T>
{
public static T MyProperty { get; set; }
}
class MyIntClass
{
public static int MyProperty { get; set; }
}
class UseThem
{
public void test()
{
// both are JIT'ed to be exactly the same machine code
var foo = MyGenericClass<int>.MyProperty;
var bar = MyOtherClass.MyProperty;
}
}
Thus, you must provide a type for the generic class so that JIT knows what to compile.
Possible Alternative
If all of the possible types which could possible end up being the generic type are similar (inherit from the same base class or implement a similar interface), then you can instantiate the generic class with an interface or base class as the generic type:
List<ComponentList<ComponentBase>> MasterList = new List<ComponentList<ComponentBase>>();
// -OR-
List<ComponentList<IMyComponent>> MasterList = new List<ComponentList<IMyComponent>>();
I have a hunch that you should be able to define a common interface or base class with a little creative refactoring. :)
I've run into this issue as well when I was trying to set up an entity-component system for a game written in C#. There's really isn't a way to store components as their actual types, you have to store them all as Components and cast them.
The way I have it set up is as a Dictionary<Type, List<Component>> as a private member of a ComponentManager class. The method that adds components is generic and checks if it's Type is contained in the Dictionary, so getting an IEnumerable<SpecificComponent> is as simple as:
public IEnumerable<T> EnumerateComponents<T>()
where T : Component
{
foreach (Component c in components[typeof(T)])
yield return (T)c;
}
(You'll also want to check that the dictionary contains typeof(T), that bit is built-in with a custom collection of mine that inherits from Dictionary to avoid exceptions in cases like this.)
Type safety is "guaranteed" as long as the dictionary is never modified outside of a generic method (and definitely not directly accessible from the outside). Not ideal, but it's fast enough where it will never be your bottleneck.
EDIT
Something to explore might be C# 4's dynamic keyword. I haven't looked into it much, but storing the components as a List<dynamic> might work better (or it may introduce way too much overhead), just something to think about.
I don't think what you are asking is possible, however maybe this is what you need.
public class ComponentA : Component { }
public class ComponentB : Component { }
public class Component { }
public class ComponentList<T> : List<T> where T : Component
{
}
class Program
{
static void Main(string[] args)
{
ComponentList<Component> MasterList = new ComponentList<Component>();
MasterList.Add(new ComponentA());
MasterList.Add(new ComponentB());
for (int i = 0; i < MasterList.Count; i++)
{
if (MasterList[i] is ComponentA)
{
}
}
}
}

C#, generic way to access different lists within a class

I have a class of 3 different linked lists (for saving the entities in a game I'm working on). The lists are all of objects with the same base type, but I keep them separate for processing reasons. Note that IEntity, IObject and IUndead all inherited from IEntity.
public class EntityBucket
{
public LinkedList<IEntity> undeadEntities;
public LinkedList<IEntity> objects;
public LinkedList<IEntity> livingEntities;
public EntityBucket()
{
undeadEntities = new LinkedList<IEntity>();
objects = new LinkedList<IEntity>();
livingEntities = new LinkedList<IEntity>();
}
public LinkedList<IEntity> GetList(IObject e)
{
return objects;
}
public LinkedList<IEntity> GetList(IUndead e)
{
return undeadEntities;
}
public LinkedList<IEntity> GetList(ILiving e)
{
return livingEntities;
}
}
I have 3 methods for retrieving each of the lists, currently based on their parameters. The fact that there are 3 is fine, since I know each list will in some way or another require its own accessor. Passing an instantiated object is not ideal though, as I may want to retrieve a list somewhere without having an object of similar type at hand. Note that the object here is not even used in the GetList methods, they are only there to determine which version to use. Here is an example where I have an instantiated object at hand:
public void Delete(IUndead e, World world)
{
.....
LinkedList<IEntity> list = buckets[k].GetList(e);
.....
}
I don't like this current implementation as I may not always have an instantiated object at hand (when rendering the entities for example). I was thinking of doing it generically but I'm not sure if this is possible with what I want to do. With this I also need 3 Delete methods (and 3 of any other, such as add and so forth) - one for each type, IUndead, IObject and ILiving. I just feel that this is not the right way of doing it.
I'll post what I have tried to do so far on request, but my generics is rather bad and I feel that it would be a waste for anyone to read this as well.
Finally, performance is very important. I'm not prematurely optimizing, I am post-optimizing as I have working code already, but need it to go faster. The getlist methods will be called very often and I want to avoid any explicit type checking.
So you want a better interface, because, as you said, passing an unnecessary object to GetList just to figure out its type makes little sense.
You could do something like:
public List<IEntity> GetList<T>() : where T:IEntity
{
if(typeof(T)==typeof(IUndead)) return undedEntities;
// and so on
}
And you'll have to call it like this: GetList<IUndead>();
I think an enum is a better idea here:
enum EntityTypes { Undead, Alive, Object };
public List<IEntity> GetList(EntityTypes entityType) { ... }
It's cleaner and makes more sense to me.
EDIT: Using generics is actually not that simple. Someone could call GetList a Zombie type, which implements IUndead, and then you'll have to check for interface implementations. Someone could even pass you a LiveZombie which implements both IUndead and IAlive. Definitely go with an enum.
How about a better implementation to go with that better interface?
public class EntityBucket
{
public LinkedList<IEntity> Entities;
public IEnumerable<T> GetEntities<T>() where T : IEntity
{
return Entities.OfType<T>();
}
}
List<IUndead> myBrainFinders = bucket.GetEntities<IUndead>().ToList();
With this implementation, the caller better add each item to the right list(s). That was a requirement for your original implementation, so I figure it's no problem.
public class EntityBucket
{
Dictionary<Type, List<IEntity>> entities = new Dictionary<Type, List<IEntity>>();
public void Add<T>(T item) where T : IEntity
{
Type tType = typeof(T);
if (!entities.ContainsKey(tType))
{
entities.Add(tType, new List<IEntity>());
}
entities[tType].Add(item);
}
public List<T> GetList<T>() where T : IEntity
{
Type tType = typeof(T);
if (!entities.ContainsKey(tType))
{
return new List<T>();
}
return entities[tType].Cast<T>().ToList();
}
public List<IEntity> GetAll()
{
return entities.SelectMany(kvp => kvp.Value)
.Distinct() //to remove items added multiple times, or to multiple lists
.ToList();
}
}
How about something like the following?
public LinkedList<IEntity> GetList(Type type) {
if (typeof(IUndead).IsAssignableFrom(type)) return undeadEntities;
if (typeof(ILiving).IsAssignableFrom(type)) return livingEntities;
if (typeof(IObject).IsAssignableFrom(type)) return objects;
}
Then you would call it like this:
var myUndeads = GetList(typeof(IUndead));
var myLivings = GetList(typeof(ILiving));
// etc
The same type of logic could be implemented in your deletes, add, and other methods, and you never need a concrete instance of an object to access them.
The IsAssignableFrom logic handles subclassing just fine (i.e. you could have a CatZombie, which derives from Zombie, which implements IUndead, and this would still work). This means you still only have to create one Delete method, something like the following:
public void Delete(IEntity e, World world) {
if (typeof(IUndead).IsAssignableFrom(type)) undeadEntities.Remove(e);
if (typeof(ILiving).IsAssignableFrom(type)) livingEntities.Remove(e);
if (typeof(IObject).IsAssignableFrom(type)) objects.Remove(e);
}
EDIT: I noticed your comment on zmbq's answer regarding performance; this is definitely NOT fast. If you need high performance, use an enum-style approach. Your code will be more verbose and require more maintenance, but you'll get much better performance.
Seems to me you could just implement a Dictionary
of named LinkedList's and refer to them
by name or enum.
That way adding or removing lists is just an
implementation issue and no separate class to deal with.

C# Covariance on subclass return types

Does anyone know why covariant return types are not supported in C#? Even when attempting to use an interface, the compiler complains that it is not allowed. See the following example.
class Order
{
private Guid? _id;
private String _productName;
private double _price;
protected Order(Guid? id, String productName, double price)
{
_id = id;
_productName = productName;
_price = price;
}
protected class Builder : IBuilder<Order>
{
public Guid? Id { get; set; }
public String ProductName { get; set; }
public double Price { get; set; }
public virtual Order Build()
{
if(Id == null || ProductName == null || Price == null)
throw new InvalidOperationException("Missing required data!");
return new Order(Id, ProductName, Price);
}
}
}
class PastryOrder : Order
{
PastryOrder(Guid? id, String productName, double price, PastryType pastryType) : base(id, productName, price)
{
}
class PastryBuilder : Builder
{
public PastryType PastryType {get; set;}
public override PastryOrder Build()
{
if(PastryType == null) throw new InvalidOperationException("Missing data!");
return new PastryOrder(Id, ProductName, Price, PastryType);
}
}
}
interface IBuilder<in T>
{
T Build();
}
public enum PastryType
{
Cake,
Donut,
Cookie
}
Thanks for any responses.
UPDATE: This answer was written in 2011. After two decades of people proposing return type covariance for C#, it looks like it will finally be implemented; I am rather surprised. See the bottom of https://devblogs.microsoft.com/dotnet/welcome-to-c-9-0/ for the announcement; I'm sure details will follow.
First off, return type contravariance doesn't make any sense; I think you are talking about return type covariance.
See this question for details:
Does C# support return type covariance?
You want to know why the feature is not implemented. phoog is correct; the feature is not implemented because no one here ever implemented it. A necessary but insufficient requirement is that the feature's benefits exceed its costs.
The costs are considerable. The feature is not supported natively by the runtime, it works directly against our goal to make C# versionable because it introduces yet another form of the brittle base class problem, Anders doesn't think it is an interesting or useful feature, and if you really want it, you can make it work by writing little helper methods. (Which is exactly what the CIL version of C++ does.)
The benefits are small.
High cost, small benefit features with an easy workaround get triaged away very quickly. We have far higher priorities.
The contravariant generic parameter cannot be output, because that cannot be guaranteed to be safe at compile time, and C# designers made a decision not to prolong the necessary checks to the run-time.
This is the short answer, and here is a slightly longer one...
What is variance?
Variance is a property of a transformation applied to a type hierarchy:
If the result of the transformation is a type hierarchy that keeps the "direction" of the original type hierarchy, the transformation is co-variant.
If the result of the transformation is a type hierarchy that reverses the original "direction", the transformation is contra-variant.
If the result of the transformation is a bunch of unrelated types, the transformation is in-variant.
What is variance in C#?
In C#, the "transformation" is "being used as a generic parameter". For example, let's say a class Parent is inherited by class Child. Let's denote that fact as: Parent > Child (because all Child instances are also Parent instances, but not necessarily the other way around, hence Parent is "bigger"). Let's also say we have a generic interface I<T>:
If I<Parent> > I<Child>, the T is covariant (the original "direction" between Parent and Child is kept).
If I<Parent> < I<Child>, the T is contravariant (the original "direction" is reversed).
If I<Parent> is unrelated to I<Child>, the T is invariant.
So, what is potentially unsafe?
If C# compiler actually agreed to compile the following code...
class Parent {
}
class Child : Parent {
}
interface I<in T> {
T Get(); // Imagine this actually compiles.
}
class G<T> : I<T> where T : new() {
public T Get() {
return new T();
}
}
// ...
I<Child> g = new G<Parent>(); // OK since T is declared as contravariant, thus "reversing" the type hierarchy, as explained above.
Child child = g.Get(); // Yuck!
...this would lead to a problem at run-time: a Parent is instantiated and assigned to a reference to Child. Since Parent is not Child, this is wrong!
The last line looks OK at compile-time since I<Child>.Get is declared to return Child, yet we could not fully "trust" it at run-time. C# designers decided to do the right thing and catch the problem completely at compile-time, and avoid any need for the run-time checks (unlike for arrays).
(For similar but "reverse" reasons, covariant generic parameter cannot be used as input.)
Eric Lippert has written a few posts on this site about return method covariance on method overrides, without as far as I can see addressing why the feature is unsupported. He has mentioned, though, that there are no plans to support it: https://stackoverflow.com/a/4349584/385844
Eric is also fond of saying that the answer to "why isn't X supported" is always the same: because nobody has designed, implemented, and tested (etc.) X. An example of that is here: https://stackoverflow.com/a/1995706/385844
There may be some philosophical reason for the lack of this feature; perhaps Eric will see this question and enlighten us.
EDIT
As Pratik pointed out in a comment:
interface IBuilder<in T>
{
T Build();
}
should be
interface IBuilder<out T>
{
T Build();
}
That would allow you to implement PastryOrder : IBuilder<PastryOrder>, and you could then have
IBuilder<Order> builder = new PastryOrder();
There are probably two or three approaches you could use to solve your problem, but, as you note, return method covariance is not one of those approaches, and none of this information answers the question of why C# doesn't support it.
Just to post this somewhere google finds it...
I was looking into this because I wanted to have an interface in which I can return collections / enumerables of arbitrary classes implementing a specific interface.
If you're fine with defining the concrete types you want to return, you can simply define your interface accordingly. It will then check at compile time that the constraints (subtype of whatever) are met.
I provided an example, that might help you.
As Branko Dimitrijevic pointed out, usually it is unsafe to allow covariant return types in general. But using this, it's type-safe and you can even nest this (e. g. interface A<T, U> where T: B<U> where U : C)
(Disclaimer: I started using C# yesterday, so I might be completely wrong regarding best practices, someone with more experience should please comment on this :) )
Example:
Using
interface IProvider<T, Coll> where T : ProvidedData where Coll : IEnumerable<T>
{
Coll GetData();
}
class XProvider : IProvider<X, List<X>>
{
List<X> GetData() { ... }
}
calling
new XProvider().GetData
works and in this case is safe. You only have to define the types you want to return in this case.
More on this: http://msdn.microsoft.com/de-de/library/d5x73970.aspx

Implementing a specific case of a generic, versus deriving from it

I am trying to write out a specific case of a generic class with additional functionality, but I am not sure why the following happens.
Suppose I have a generic class:
class Generic<T>
{
protected T value;
}
If I write out a specific implementation, I can't actually use the specific type I've narrowed it down to:
EDIT: I goofed up, this doesn't work.
class Generic<float>
{
// This doesn't work
public void Add()
{
value + 1.0f;
}
}
But if I inherit from the specific version, it does work:
class Specific : Generic<float>
{
// This does work
public void Add()
{
value + 1.0f;
}
}
In case someone is still reading this, I wanted to point out that this seems to be possible with extension methods:
class Generic<T>
{
public T value;
}
static class Extension
{
public static void Add (this Generic<float> generic)
{
generic.value += 1.0f;
}
}
The downside seems to be that 'value' has to be public or internal.
Your first attempt simply isn't a valid declaration - the part that specifies a class can't specify any type arguments.
If you think about it, how would the CLR know whether or not there was a specialized type available? What would it do if there were two different specializations of the same generic type in two loaded assemblies? It would have to check all the referenced assemblies any time a particular type argument combination was used for the first time. (This couldn't be done at compile-time, as other classes may just be referring to Generic<T>.)
In many cases you can use values of the type in ways which are meaningful to the type using constraints. For example, if you constrain T with where T : IComparable<T> then you can compare any two T values using Compare. Unfortunately there's no way of representing arithmetic operators in this way, although you may want to look at Marc Gravell's generic operator work in MiscUtil.
While I feel your pain, there's simply nothing like this in .NET generics - you'll want to think of alternative designs for whatever problem you're really trying to solve.
in this case :
class Generic<float>
{
// This doesn't work
public void Add()
{
value + 1.0f;
}
}
It doesn't mean that you are working with a Generic class using float as its generic type but it means that the name of the generic type is "float" in the source (instead of using T you are using "float" as its name ) Thus there's no conversion to float.In other words you are using a generic notation as a template that can be substituted with real types later (but not in the template itself and that's why in C++ they are called templates)
In this code :
class Specific : Generic<float>
{
// This does work
public void Add()
{
value + 1.0f;
}
}
you are telling the compiler that you want the specific class be a child of a generic class while it's template type will be replaced by type float.
Generic types are used for arithmetic reusability. That is, you must write something common between all possible Ts in your code.
class Generic<T>
{
protected T value; //it's valid to declare a member whose type is T
public void Add()
{
value + 1.0f; //invalid, because not all T are allowed to add
//with 0.1f by default
//consider T is the type Person
}
public void Print()
{
Type t = typeof(T); //valid, for all T we can get its type
}
}
And when you specified some T (e.g. float in your question), the compiler knows the T is float, so it's valid to add 0.1f to it.
I also looked for similar solution, I think you also got this thinking from ADA or such programming language.
But, as others wrote, making type specific class definition is not generic programming, it's specialization, so the simpliest (and only in C#) way is to create a specified class, based on generic structure:
class Generic<T>
{
protected T value;
public Generic(T val)
{
value = val;
}
}
class Generic_float : Generic<float>
{
public Generic_float(float val)
: base(val)
{
}
public void Add()
{
value = value + 1.0f;
}
}
As you can see, we created a class for the specified case, having the extra ability of extending the structure with fields and methods. This advantage is very good to refine behavior of our objects, and gives ability of implicit cast of the typed generic class to our customized one (with the notice that casting back is not possible):
public void Test()
{
Generic<float> var1 = new Generic<float>(1.5f);
Generic_float var2 = new Generic_float(2.5f);
var1 = var2; // Works, var links to var2's memory field casted as Generic<float>
var2 = var1; // cannot implicitly convert error, if want to use then have to make explicit conversion
}
Don't know if the way you expected should work in languages like C# or other managed ones, but maybe this workaround gives you what you really wanted to get.

Calling a specific constructor in C# with null

I have a class with several constructors and I want to call the "main" one from another - but using null.
Using just this(null) results in a compile time error, so I cast null to the type of the other constructor. Compiles fine.
MyClass
{
public MyClass(SomeType t)
{ }
public MyClass(IList<FooType> l)
: this((SomeType)null)
{ }
}
This feels, lets just say icky. Is this okay and common or insane and shows a flaw in the class - in that it should have an empty constructor?
The class "mostly" requires a SomeType, but there are rare times when it is okay to not have one. I want the rare times to "stick out" and be obvious that something "is not a-typical" with the code.
You need the cast because null by itself is ambiguous. A null by itself has no inherent type, so the cast tells the compiler which constructor you want to pass null to.
That being said, it is probably more meaningful for your class to use a default (no-arg) constructor, like you said. Having all three constructors is probably okay, too.
It does have just a slight smell to it. This technique is used sometimes, but I would avoid it if practically possible.
A parameterless constructor is generally more descriptive than passing null, you can make it private if you only use it from within the class:
MyClass {
private MyClass() {
}
public MyClass(SomeType t) {
}
public MyClass(IList<FooType> l) : this() {
}
}
Another alternative (but one that doesn't work to call from a constructor) is to put the code in a static method to somewhat isolate it and give it a more descriptive name:
MyClass {
public MyClass(SomeType t) {
}
public static MyClass CreateEmptyInstance() {
return new MyClass((SomeType)null);
}
}
In my honest opinion this seems like a logic flaw, that will get you into trouble somewhere down the road. It just seems that at some point a piece of code will be written that will do some validation and break this constructor and you will waste a massive amount of time debugging it. I do need to further see what it is you are trying to do and why.
I use the "view model first" pattern for MVVM development in WPF/C#, so I'm required to have an empty constructor. Because of that, I invert your pattern and use a nullable as the parameter for design-time. No casting of null required as long as it's the only constructor with that number of parameters.
public FooClass
{
public FooClass() : this(null) { }
public FooClass(Bar? bar)
{
_bar = bar ?? new();
// Whatever else initialization for the class.
}
public Bar Bar { get; set; }
}

Categories

Resources