C# 4.0: dynamic 'this' pointer - c#

Is it possible to allow methods and properties of the 'this' pointer to be resolved dynamically?
Put another way, can a class have a dynamic superclass?
Clarification
I would like to be able to subclass some class and access properties and methods that aren't defined at compile-time.
class MyClass : DynamicObject
{
public void ReceiveValue(object value) {
MyProperty = value;
}
}
DynamicObject provides a way for my code to get notified that set_MyProperty has been called with the argument value above, correct? I know this is possible if you use a syntax like:
var mc = new MyClass();
...
dynamic dmc = mc;
dmc.MyProperty = value;
But I want to be able to do this from within the methods of MyClass, almost as if I had done:
dynamic dmc = this;
dmc.MyProperty = value;
Does DynamicObject have me covered?

No, you can't have a dynamic base class. Aside from anything else, the system still needs to know how much space to allocate when you create a new instance of your class.
Could you explain what you're trying to achieve? There may well be ways in which dynamic would help without needing quite this behaviour.
EDIT: Okay, having seen your edit - I don't think you can quite do what you want, but if you just use the
dynamic dmc = this;
dmc.MyProperty = value;
or
((dynamic)this).MyProperty = value;
workaround it should be fine. To put it another way: the this reference is always statically typed, but you can have an expression with the value of this but with a dynamic type.
That shouldn't be too onerous unless you're doing a lot of dynamic work - in which case I'd recommend that you use a fully dynamic language instead. If you implement the bulk of your dynamic code in IronPython/IronRuby, you can easily integrate it with your C# code anyway.

This is the basis of polymorphism. The method/property called will be the one given lowest in the heirarchy of the objects type.

How about this:
class B
{
public void M(object o)
{
dynamic i = this;
i.P = o;
}
}
class D : B
{
public object P { get; set; }
}
class Program
{
static void Main()
{
var d = new D();
d.M(1);
}
}

I realize this is a tangent, but there are languages where every class's superclass is dynamic - i.e. where class name resolution is virtual and override-able.

Related

Reflection : Get the real type of a initialized auto-property (C#6)

I have a class declared like this :
public class MyClass
{
public IMyInterface1 Prop1 { get; } = new MyImplementation1();
public IMyInterface2 Prop2 { get; } = new MyImplementation2();
public IMyInterface3 Prop3 { get; } = new MyImplementation3();
//[...]
}
I would like the list of implemented types, using reflection.
I dont have an instance of MyClass, just the type.
Ex:
static void Main(string[] args)
{
var aList = typeof(MyClass).GetProperties(); // [IMyInterface1, IMyInterface2, IMyInterface3]
var whatIWant = GetImplementedProperties(typeof(MyClass)); // [MyImplementation1, MyImplementation2, MyImplementation3]
}
IEnumerable<Type> GetImplementedProperties(Type type)
{
// How can I do that ?
}
PS: I'm not sure the title is well adapted, but I have found nothing better. I am open to suggestions.
Reflection is type metadata introspection, thus, it can't get what an actual instance of a given type may contain in their properties unless you provide an instance of the so-called type.
That's the main reason why reflection methods like PropertyInfo.GetValue have a first mandatory argument: the instance of the type where the property is declared on.
You're in the wrong direction if you want to use reflection for this. Actually you need a syntax analyzer and luckily, C# 6 comes with the new and fancy compiler formerly known as Roslyn (GitHub repository). You can also use NRefactory (GitHub repository).
Both can be used to parse actual C# code. You can parse the whole source code and then get what classes are returned in expression-bodied properties.
You can't get real types without class instance, because properties are initialized only for instances. For instance of the class, you can do something like that
List<Type> propertyTypes = new List<Type>();
PropertyInfo[] properties = typeof(MyClass).GetProperties();
foreach(PropertyInfo propertyInfo in properties)
{
propertyTypes.Add(propertyInfo.GetValue(myClassInstance));
}

Generics and objects conversion in C#

I have a class which is handling objects same way.
It's like:
class Handler<T>{
private T _obj;
public T obj{
get{
...//do sth
return _obj;
}
set{
...//do sth
_obj = value;
}
}
... // some other properties, no T anymore
}
There are large amount of code working on Handler objects, ignoring type. I mean, type T is not for them, there are setting other fields.
There are containers with Handler<> and so on.
At the end I need to return Handler with correct type.
I wanted to use Handler<object>, but there is no way I know to convert it to Handler<SomeClass>.
How can I handle situtations like this?
Why don't you make a base class for Handler<T>, which will contain all non-generic code?
class HandlerBase
{
// some other properties
}
class Handler<T> : HandlerBase
{
public T obj { ... }
}
If your "large amount of code" ignores T, than let it work with HandlerBase.
You can try with an IHandler interface.
IHandler<SomeClass> h1 = new Handler<SomeClass>();
IHandler<Object> h2 = h1;
This will work !
More info on Covariance on MSDN

Access property of a object without needing to cast it

I have the following three classes
public class Base
{
string name;
}
public class Foo : Base
{
int value;
}
public class Bar : Base
{
double value;
}
This is what I'm attempting
Base current = null;
if (somecondition)
current = new Foo();
else
current = new Bar();
for (int i=0; i<5; i++)
{
current.value = i;
}
The problem is VS 2010 shows an error in the loop body because Base doesn't have a property value.
Now, I could workaround this issue by this way:
Base current = null;
bool isBar = true;
if (somecondition)
{
current = new Foo();
isBar = false;
}
else
current = new Bar();
for (int i=0; i<5; i++)
{
if (isBar)
(current as Bar).value = i;
else
(current as Foo).value = i;
}
But I was hoping for a better solution because once the loop starts iterating, the type of current isn't going to change, yet I am going to test the type and accordingly cast it for each iteration.
What would be the right way to do this?
After making the fields accessible (or exposing them as accessible properties instead), your options are:
Make your base class abstract, with an abstract method or property to set the value (and possibly return it) - the problem here is that you can't easily do that when the two types are different
Create an interface to do the same sort of thing, and cast to the interface
Just cast as you are now
Use dynamic if you're using C# 4 - just declare current as dynamic, and you can assign to current.value and the compiler will insert code to work it out at execution time
Redesign your code / inheritance hierarchy
Personally I would at least consider the last approach - is inheritance definitely appropriate here? Do the two types for value really need to be different? Do they have the same meaning, and if so would it make sense to push the value to the base class and potentially make it generic if you need different types?
You could instead of using a base class create an interface that has Value as a property and then have Foo and Bar implement that interface.
First, your "value" fields are not exposed as public.
Second, I don't think you won't get away from explicit casting here. Just imaging that your Bar class look like this:
public class Bar : Base
{
public string value;
}

Encapsulation questions in C#

I'm having some problems with encapsulation in C#. There are two specific scenarios that are causing me problems and I believe the issue is related.
Scenario #1
I have a class definition that looks something like this
class MyClass
{
private int _someField;
private OtherClass _otherClass;
public int someField
{
get { return _someField; }
set { _someField = value; }
}
public OtherClass otherClass
{
get { return _otherClass; }
set { _otherClass = value; }
}
}
If I then try and do something like this in a new piece of code
MyClass theClass = new MyClass();
theClass.otherClass.XYZ += 1;
I get told Cannot Modify the return value of 'MyClass.otherClass' because it is not a variable.
Scenario 2#
public partial class trksegType
{
private wptType[] trkptField;
private extensionsType extensionsField;
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute("trkpt")]
public wptType[] trkpt
{
get
{
return this.trkptField;
}
set
{
this.trkptField = value;
}
}
}
If I now try and foreach through the wptType array:
foreach (wptType way in trk.trkseg[i])
I get told - foreach statement cannot operate on variables of type 'trksegType' because 'trksegType' does not contain a public definition for 'GetEnumerator'
Even though an array should implicitly allow enumeration.
Can anyone explain what's going on and what I can do to get around this problem, whilst still maintaining best practices.
For scenario 1, I suspect that OtherClass has been defined as a struct. When a struct is accessed from a property accessor a new copy of the struct is created and returned (structs are value types). Changing a property on this new copy will have no effect on the original struct.
The C# compiler detects this and raises that slightly obscure error.
Scenario 1:
The reason is very likely because your OtherClass is a struct and not a class. Value sematics are a bit tricky and mutable value types are considered harmful. So you either want to make OtherClass a class and not a struct or you do something along those lines:
struct OtherClass
{
public int XYZ { get; }
public OtherClass(int xyz)
{
XYZ = xyz;
}
public OtherClass AddToXYZ(int count)
{
return new OtherClass(this.XYZ + count);
}
}
Then you can do
myClass.otherClass = myClass.otherClass.AddToXYZ(1);
Scenario 2:
You either need to implement IEnumerable on trksegType to enumerate over trkpt or actually access trkpt for the enumeration.
In General:
You have violated encapsulation in both scenarios by accessing objects through other objects. Have a look here: http://www.csharp-station.com/Tutorials/lesson19.aspx
You also should consider using better (more explicit) names for your objects. mttng vwls ds nt ncrs rdblty.
(You really shouldn’t post two questions in one.)
Scenario 1
Cannot Modify the return value of 'MyClass.otherClass' because it is not a variable.
This error happens because OtherClass is not a class, but a struct — also called a value type. This means that accessing MyClass.otherClass copies the value instead of returning a reference. You would be modifying this copy, which would be pointless. The compiler catches this because it is always a bug and never useful.
Scenario 2
foreach (wptType way in trk.trkseg[i])
You haven’t told us what trkseg[i] is, but if it is of the type trksegType, then the answer is: because trksegType doesn’t allow any enumeration. It does not implement IEnumerable, IEnumerable<T>, nor does it have a GetEnumerator method of its own.
Perhaps you meant to write:
foreach (wptType way in trk.trkseg[i].trkpt)
because trkpt is an array of wptType. (You might have found this error sooner if you used more meaningful variable names instead of weird combinations of letters that make no sense.)
I can't see anything wrong with your first example - so double check that the sample that errors really does and correct if not.
In the second instance, it looks like you're trying to iterate on an instance of trksegType, rather than the contained trkpt property. Try foreach (wptType way in trk.trkseg[i].trkpt) instead.

Accessing non-generic members of a generic object

Is there a way to collect (e.g. in a List) multiple 'generic' objects that don't share a common super class? If so, how can I access their common properties?
For example:
class MyObject<T>
{
public T Value { get; set; }
public string Name { get; set; }
public MyObject(string name, T value)
{
Name = name;
Value = value;
}
}
var fst = new MyObject<int>("fst", 42);
var snd = new MyObject<bool>("snd", true);
List<MyObject<?>> list = new List<MyObject<?>>(){fst, snd};
foreach (MyObject<?> o in list)
Console.WriteLine(o.Name);
Obviously, this is pseudo code, this doesn't work.
Also I don't need to access the .Value property (since that wouldn't be type-safe).
EDIT: Now that I've been thinking about this, It would be possible to use sub-classes for this. However, I think that would mean I'd have to write a new subclass for every new type.
#Grzenio
Yes, that exactly answered my question. Of course, now I need to duplicate the entire shared interface, but that's not a big problem. I should have thought of that...
#aku
You are right about the duck typing. I wouldn't expect two completely random types of objects to be accessible.
But I thought generic objects would share some kind of common interface, since they are exactly the same, apart from the type they are parametrized by. Apparently, this is not the case automatically.
I don't think it is possible in C#, because MyObject is not a baseclass of MyObject. What I usually do is to define an interface (a 'normal' one, not generic) and make MyObject implement that interface, e.g.
interface INamedObject
{
string Name {get;}
}
and then you can use the interface:
List<INamedObject> list = new List<INamedObject>(){fst, snd};
foreach (INamedObject o in list)
Console.WriteLine(o.Name);
Did it answer your question?
C# doesn't support duck typing. You have 2 choices: interfaces and inheritance, otherwise you can't access similar properties of different types of objects.
The best way would be to add a common base class, otherwise you can fall back to reflection.

Categories