Do you think generic properties would be useful in .NET? [closed] - c#

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 4 months ago.
Improve this question
I'm not talking about generic classes that declare properties or fields with the type of a generic parameter. I'm talking about generic properties which could be applied to both generic and non-generic classes.
I'm not talking about this:
public class Base<T>
{
public T BaseProperty { get; set; }
}
I'm talking about this:
public class Base
{
public T BaseProperty<T>
{
get
{
// Insert magic
}
set
{
// Insert magic
}
}
}
Or this:
public class Base<U>
{
public T BaseProperty<T>
{
get
{
// Insert magic
}
set
{
// Insert magic
}
}
public U OtherBaseProperty { get; set; }
}
The usage would go something like this:
var b = new Base();
b.BaseProperty<int> = 42;
int i = b.BaseProperty<int>;
b.BaseProperty<string> = "Hi";
string s = b.BaseProperty<string>;
Or for the second example:
var b = new Base<string>();
b.BaseProperty<int> = 42;
int i = b.BaseProperty<int>;
b.OtherBaseProperty = "Hi";
string s = b.OtherBaseProperty;
The // Insert Magic refers to handling each call to the generic property getter or setter that has a different type for the type parameter.
For example this:
b.BaseProperty<int> = 42;
Needs to be handled differently to:
b.BaseProperty<string> = "Hi";
I would envisage that for each type T if the getter is called before the setter is called then default(T) is returned.
When the setter is called the value is stored per type T so that when the getter is subsequently called the previous value that was set for that type is returned.
Note that under the covers properties are just methods.
Do you think this would be useful?

I've had a couple of times where I would have liked the ability to do this, yes.
However, the syntax involved would be pretty ugly, and it's sufficiently rarely useful that I think I prefer to just suck it up and go with generic methods.

No .

Without a killer use case, no. You can already achieve the same thing with a pair of generic methods, should you need it.

No.
Generic methods make sense, because they embody some (generic) operation that can sensibly be applied to different types.
But properties only make sense as uniquely named values with definite content. 'Generic properties', like you suggest, really only amounts to like-named properties with different signature and different content.

Here's one example where it would have been handy for me, if it would have been possible.
var settings = new Settings();
int timeout = settings<int>["CacheInMinutes"];
Where Settings loads an XML file of configuration variables.
That, compared to:
var settings = new Settings();
int timeout = int.Parse(settings["CacheInMinutes"]);
Really not much of a difference, but hey, I still would have preferred the generic indexer.

well, I have the situation that need generic property in non-generic class.
Example you have IComponent class that want to provide its parent IContainer with property Parent, since the component can belong to any container type. so you need to provide generic property rather than generic method
Component c = new Component();
Container p = new Container();
p.Add(c);
and then you access its parent using generic property (not aplicable now)
c.Parent.ContainerProperty;
c.Parent.ContainerMethod();
rather using verbose method like
c.Parent().ContainerProperty;
c.Parent().ContainerMethod();
Well, in this case generic property is more beautiful and make sense, since you don't need to input any argument.

If for some bizarre reason you decided you wanted it, you could sort of fake it with methods:
public class Thing
{
Dictionary<Type, object> xDict = new Dictionary<Type,object>();
public void set_X<T>(T x)
{
xDict[typeof(T)] = x;
}
public T get_X<T>()
{
return (T)xDict[typeof(T)];
}
}
Why you would want to is an entirely different matter, though. It generally makes more sense to start with something you want to do than some way you want to do it.

Related

Is it possible to assign a property of a class assigning it to the instance of that class?

To further explain: i have a class let's say A, with a property of type let's say X; what i would like to do is to be able to instantiate A somewhere and assign the attribute using the instance without accessing the property itself or using methods, and possibly doing some other operation. Something like this:
public class A
{
private X _inside; //it actually can be public also
private DateTime _timeStamp;
public A() {X = new X();}
}
A anInstance = new A();
X aParameter = new X();
anInstance = aParameter
aParameter should be set to the _inside property of anInstance, while also assign DateTime.UtcNow to _timeStamp. Is it possible to do so? I am aware that doing so through a method or get and set is way easier, i'd get the same result and is possibly more efficient, but i would like to do so.
Also, I don't know if this thing has a specific name, therefore this question may be a duplicate; I am highlighting this because i had a problem with circular headers once but i didn't know that they were called so and my question was marked as a duplicate (not an english native seaker), which is not a problem as long as pointing we have an answer.
Anyway, thanks in advance!
Edit lexicon fixed as suggested in the comments
I believe what you're asking for is similar to VB classic's default properties1. Imagine that C# (and .NET in general) had adopted this concept, and that we're allowed to declare one2:
//Not legal c#
public class A
{
public default A _inside {get;set; }
private DateTime _timeStamp;
public A() {}
}
It's perfectly legal for classes to have properties of their own types, and introducing restrictions just for these default properties to avoid the problems I'm about to talk about are worse than disallowing the existence of these default properties3.
So you now have the code:
A anInstance = new A();
A aParameter = new A();
anInstance = aParameter;
Pop quiz - what does line 3 do? Does it assign _inner? Of does it reassign anInstance?
VB classic solved this issue by having two different forms of assignment. Set and Let. And it was a frequent source of bugs (Option Explicit being off by default didn't help here either).
When .NET was being designed, the designers of both C# and VB.Net looked at this and said "nope". You can have indexers (c#)/default properties (VB.Net) but they have to have additional parameters:
public class A
{
private Dictionary<int,A> _inner = new Dictionary<int,A>();
public A this[int i] {
get { return _inner[i]; }
set { _inner[i] = value; }
}
private DateTime _timeStamp;
public A() {}
}
And now we can disambiguate the different assignments in a straightforward manner:
A anInstance = new A();
A aParameter = new A();
anInstance = aParameter;
anInstance[1] = aParameter;
Lines 3 and 4 are, respectively, reassigning the reference and reassigning the property value.
1VB.Net does have default properties but, as discussed later, they're not precisely the same as VB classic's.
2Note that we can't assign it an instance in the constructor now - that would lead to a stack overflow exception since constructing any instance of A would require constructing an additional instance of A which would require constructing an additional instance of A which would...
3A concrete example of this would be a Tree class that has subtrees and a SubTree class that inherits from Tree and has a Parent property of tree. If that were the "default property" for the SubTree class you'd encounter these same property/reference assignment issues discussed lower down if trying to assign a parent of a subtree of a subtree.
Which basically means that you have to disallow default properties of both the actual type in which it's declared and any type to which it's implicitly convertible, which includes all types in its inheritance hierarchy.
Did you think about inheritance?
public class A : X
{
private DateTime _timeStamp;
public A() : base() {}
}
A anInstance = new A();
X aParameter = new X();
anInstance = (A)aParameter;

Best approach to instantiate object based on string

I'd like to discuss about the best approach (in C#) to instantiate an object based on an input string. Let me explain.
Let'say I have a base class:
public abstract class BaseCar
{
public asbtract int GetEngineID();
//Other stuff...
}
Then I have several implementations of this class, let's say:
public class SportCar : BaseCar
{
public override int GetEngine()
{
//Specific implementation
}
}
public class OtherCar: BaseCar
{
public override int GetEngine()
{
//Specific implementation
}
}
And so on...
What I'd like to do is to make a static CarFactory class which has a CreateCar method which accepts a string as a parameter and returns a BaseCar instance, depending on what string you give. The string would be a name of a child class.
For example, if I call CarFactory.CreateCar('SportCar') it should return a SportCar instance.
I know I could use a simple switch statement to check which car has been requested and create a new instance based on that but I don't like this approach for two reasons:
I plan to have a lot of child classes, hard-coding every case wouldn't be too easy to mantain
I plan to implement an inizialization procedure to also give some initial values to the objects I create (using Reflection), so mixing hard-coding and reflection doesn't seem to be a good idea for me.
What I was thinking about is to use the Assembly.CreateInstance from System.Reflection to create an instance of the specified class but since this is the first time I approach this problem, I don't know if there are better ways to do that. Is this a valid approach ?
Considering the input string will come from an XML file, is there a simplier method ? Maybe my issue is already handled in some .NET Assembly which I'm missing.
Here is what I came up with. A generic factory class that automatically registers all types that are a subclass of the given type, and allows you to instantiate them via their name. This is somewhat related to the approach shown in the Java SO question linked by #Achilles in the comments, only that there is no initialisation function associated with the type.
There is no need to maintain an enum/switch combination of all types. It should also be somewhat easily extendable to handle your proposed reflection based initialisation.
static class StringFactory<T> where T : class
{
static private Dictionary<string, Type> s_dKnownTypes = new Dictionary<string, Type>();
static StringFactory()
{
RegisterAll();
}
static private void RegisterAll()
{
var baseType = typeof(T);
foreach (var domainAssembly in AppDomain.CurrentDomain.GetAssemblies())
{
foreach (var type in domainAssembly.GetTypes()
.Where(t => t.IsSubclassOf(baseType)))
{
s_dKnownTypes.Add(type.Name, type);
}
}
}
static public T Create(string _sTypeName)
{
Type knownType;
if (s_dKnownTypes.TryGetValue(_sTypeName, out knownType))
{
return (T)Activator.CreateInstance(knownType);
}
throw new KeyNotFoundException();
}
}
Assuming the classes of your question exist, you would instantiate a specific car like this:
var car = StringFactory<BaseCar>.Create("SportsCar");
DoSomethingWith(car.EngineID());
Since your question was for a discussion about the best approaches, please consider this only one of them. I have not used this in a production environment, and it is entirely possible that it is the wrong approach to your specific situation. It works well enough to show the general principle, however, and should provide a starting point for further discussion.

How to pass object attributes as function parameters?

I am designing a 3 layer framework
I would like to know if It's possible to pass attribiutes of an object to a function without declaring them explicitly ?
For example If I want to pass Id,Name to personnelBL.ValidateInsert(...)
I don't want the ValidateInsert function interface look like this : ValidateInsert(Id,Name)
The reason for that is that I want to write a base abstract class to contain a ValidateInsert(...)
abstract function so I will Inherit from that class in my BL Layer classes and If the ValidateInsert input parameters could be declared in a way that I could pass an object attribiutes in a general form It would really be nice .
Note: Someone might say that I can pass an object to the function using generics but I really don't want to pass an object ! I want to pass any object's attribiutes so I can Inherit that abstract base class in any entityBL classes .
I really could not explain what I want better ! Sorry for that and thanks for understanding me .
not sure that I fully understand what you want , but I think the below can help
You can use reflection.You can avoid the performance issues, is you create method per class on the fly and compile it (can use compile expression tree). and add your own attribute that you put only on relevant attributes.
Create an Interface, It can return dictionary of column name and their values. your abstract class will implement this interface.
hope this answer your question
I am not sure if i understand your question correctly, but are you looking for something similar to this-
public class Base<T, TFiled>
{
public void ValidateInsert(TFiled filed)
{
}
}
public class Derived : Base<Derived, long>
{
public long Id { get; set; }
}
public class AnotherDerived : Base<Derived, string>
{
public string IdSring { get; set; }
}
public class MyObject
{
private Derived d = new Derived();
private AnotherDerived anotherIsntance = new AnotherDerived();
public MyObject()
{
d.ValidateInsert(10);
anotherIsntance.ValidateInsert("some string");
}
}
Well, not really.
But you can get very close to!
You can use the Expression API. It's awesome. The code I'll post here is just pseudocode but you'll get the idea. I'll not worry about syntax but I'll try the hardest I can.
public static bool ValidateInsert(params Expression<Func<object,object>>[] properties)
{
//Here you'll do some code to get every property. You can do a foreach loop.
//I think you will need to use reflection to get the property values
} //Change Func<Object,Object> accordingly. This represents a function that takes an object and returns another object.
This is how you can achieve the syntax, but I'm not sure about functionality.
You'll need an "instance" object where you'll get the properties values from.
So, you could call it like this:
ValidadeInsert(x => x.Id, x => x.Name, x => x.Whatever)
Here you can see how to get the Getter method of a property. I think you can get the PropertyInfo from the lambda expression, but I'm not sure. You'll have to do some research and adapt it to your code, if you decide to follow this way.
Sorry about my english, but I think you understood what I meant.

What is the purpose of get : set? [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 9 years ago.
Improve this question
Many code samples in C# contain get and set code blocks. What is the purpose of them? I copy these blocks whey they appear in sample code, but have no idea what it is used for. Can someone please explain this to me?
Getters and setters enable you to combine a pair of functions into one property, and let you use a syntax that looks like a member access expression or an assignment in place of syntax that looks like an explicit function call.
Here is a small example: instead of this
internal class Example
{
private int x;
public int GetX() => x;
public void SetX(int value) => x = value;
}
...
var e = new Example();
e.SetX(123);
Console.WriteLine($"X = {e.GetX()}");
They let you do this:
internal class Example
{
public int X { get; set; }
}
...
var e = new Example();
e.X = 123;
Console.WriteLine($"X = {e.GetX()}");
The syntax of the second code snippet is easier to read, because X looks like a variable. At the same time, the second snippet provides the same level of encapsulation, letting you hide the implementation behind the property.
Do you mean this?:
public int SomeValue { get; set; }
This is basically syntactic shorthand for this:
private int someValue;
public int SomeValue
{
get { return someValue; }
set { someValue = value; }
}
Which itself is basically shorthand for this:
private int someValue;
public int GetSomeValue() { return someValue; }
public void SetSomeValue(int value) { someValue = value; }
(Though the compiler uses different conventions for the names of things when it does this.)
As it relates to OOP, this is the encapsulation of data. The idea is that objects should hide their data and expose functionality, instead of just exposing the data directly. So you don't necessarily modify someValue directly from outside the object. You call a method on the object and supply it with a value. Internally the object handles the actual storage of its data.
public int foo { get; set; }
This defines a property. It's basically like a public field but when it comes to reflection it's different. In C#/.NET it's common to use properties for public things. You can compare it with getter/setter methods in Java.
The awesome thing now is, that you can also use custom get/set code or make set less visible than get. That allows you to have the advantages of getter/setter methods without the ugliness of method calls instead of property accesses.
public int foo {
get { return this.some_foo; }
set { this.some_foo = value; this.run_code_after_change(); }
};
In english they are setters and getters.
Hope you teach yourself encapsulation, setters and getters were rised due to encapsulation.
Again in plain english, setters and getters give you the ability to access the property you define.
get and set are kind of syntactic sugar. It is the more readable way of implementing functions getting no params where you can insert for example validation (in setter) or calculations on fields in getters. Parentheses are useless in function like that.

Why does C# not allow generic properties?

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; }
}

Categories

Resources