Is this a hole in dynamic binding in C# 4? - c#

I've seen a very interesting post on Fabio Maulo's blog. Here's the code and the bug if you don't want to jump to the url. I defined a new generic class like so:
public class TableStorageInitializer<TTableEntity> where TTableEntity : class, new()
{
public void Initialize()
{
InitializeInstance(new TTableEntity());
}
public void InitializeInstance(dynamic entity)
{
entity.PartitionKey = Guid.NewGuid().ToString();
entity.RowKey = Guid.NewGuid().ToString();
}
}
Note that InitializeInstance accepts one parameter, which is of type dynamic. Now to test this class, I defined another class that is nested inside my main Program class like so:
class Program
{
static void Main(string[] args)
{
TableStorageInitializer<MyClass> x = new TableStorageInitializer<MyClass>();
x.Initialize();
}
private class MyClass
{
public string PartitionKey { get; set; }
public string RowKey { get; set; }
public DateTime Timestamp { get; set; }
}
}
Note: the inner class "MyClass" is declared private.
Now if i run this code I get a Microsoft.CSharp.RuntimeBinder.RuntimeBinderException on the line "entity.PartitionKey = Guide.NewGuid().ToString()".
The interesting part, though is that the message of the exception says "Object doesn't contain a definition for PartitionKey".
alt text http://img697.imageshack.us/img697/4188/testdl.png
Also note that if you changed the modifier of the nested class to public, the code will execute with no problems. So what do you guys think is really happening under the hood? Please refer to any documentation -of course if this is documented anywhere- that you may find?

The binder tries to work out an accessible class to treat the object as - in this case, the code making that call doesn't "know" about the MyClass class, so it doesn't "know" about PartitionKey either.
I don't know how thoroughly this is documented in the C# 4 spec - I know I've had an email conversation about it with Chris Burrows though, so the details may be somewhere on his blog :) Bear in mind that the dynamic binding has changed over time, so more recent posts are likely to be more accurate with respect to the RTM code.
I think that if you put PartitionKey into a public interface that the private class implements, that may work - but you'd have to try it.
There are various "gotchas" around dynamic typing. Explicit interface implementation has a similar problem:
public int Count(IList list)
{
int count1 = list.Count; // Fine
dynamic d = list;
int count2 = d.Count; // Should work, right?
}
This will fail if you pass in an array - because although IList.Count exists, it's implemented explicitly in arrays - so it's a bit like this:
string[] array = new string[10];
Console.WriteLine(array.Count); // Won't compile
The binder tries to treat the object as its concrete type, not as IList, hence the failure...

Related

Comparison of unspecified generic properties

Consider the following code:
public interface IIdentifiable<T>
{
T Id { get; set; }
}
public interface IViewModel
{
}
public class MyViewModel1 : IViewModel, IIdentifiable<int>
{
public string MyProperty { get; set; }
public int Id { get; set; }
}
public class MyViewModel2 : IViewModel, IIdentifiable<string>
{
public string MyProperty { get; set; }
public string Id { get; set; }
}
I also have class that operates with ViewModels:
public class Loader<T> where T: IViewModel
{
public void LoadData()
{
/*some important stuff here*/
if (typeof(IIdentifiable<??>).IsAssignableFrom(typeof(T)))
{ // ^- here's the first problem
data = data.Where(d => _dataSource.All(ds => ((IIdentifiable<??>) ds).Id != ((IIdentifiable<??>) d).Id)).ToList();
} // ^---- and there the second ----^
/*some important stuff here too*/
}
}
Now, as you can see, viewmodels that I have might implement the IIdentifiable<> interface. I want to check that, and if it's true,
I want to make sure my data list does not contains any entry that are already present in my _dataSourse list.
So I have 2 questions:
I don't know what IIdentifiable<> has in its generic parentheses, it might be int, string or even GUID.
I tried typeof(IIdentifiable<>).IsAssignableFrom(typeof(T)) which is the correct syntax, yet it always returns false.
Is there a way to check whether T is IIdentifiable<> without knowing the exact generic type?
If there is an answer for the first question, I would also like to know how can I compare the Id fields without knowing their type.
I found this answer quite useful, yet it doesn't cover my
specific case.
I know that I probably can solve that problem if I make my Loader<T> class a generic for two types Loader<T,K>, where K would be the
type in IIdentifiable<>, yet I would like to know if there are other solutions.
P.S. In addition to my first question: I'm also curious why one can write something like this typeof(IIdentifiable<>).IsAssignableFrom(typeof(T)) if it returns false when the generic type of IIdentifiable<> is not specified?
Edit: I guess, in hindsight, I understand why I can't write the code this bluntly - because there's might be the collection ICollection<IViewModel> where the entries implement different types of IIdentifiable<> (or don't implement it at all), and the check like that would fail awkwardly. Yet maybe there is a way to do something like that with some restrictions, but without creating second generic parameter to my Loader?
Try add two methods to your Loader<T>:
public bool CanCast<TId>()
{
var identifiableT = typeof(IIdentifiable<>).MakeGenericType(typeof(TId));
return identifiableT.IsAssignableFrom(typeof(T));
}
public IEnumerable<IIdentifiable<TId>> Filter<TId>(IEnumerable<T> data)
{
return data.Where(d => _dataSource.All(
ds => !((IIdentifiable<TId>) ds).Id.Equals(((IIdentifiable<TId>) d).Id)));
}
Then in LoadData
if (CanCast<int>())
data = Filter<int>(data);
else if (CanCast<Guid>())
data = Filter<Guid>(data);
// and so om
Well, I would suggest you to always use a string for identification. You can convert int and guid to a string. And if you want to ensure proper type is used then you can prefix the string with type information.
However, I do think that the performance of you algorithm would be very poor as you wouls essentially loop 2 containers so it would be O(n * m).
Thus it would be best to either do appropriate SQL query if both sources are from the database or use a dictionary if you do it in code. Alternatively if data is properly sorted, you could find duplicates more efficiently.
By the way generics are quite limited in C#. Sometime using ˋFunc<>ˋ could help but even then you have to provide extra information to the algorithm.
We should address your question in two steps (because there really are two problems to solve here).
First, make following change to your interface IIdentifiable<T>
public interface IIdentifiable<T>
where T : IEquatable<T>
{
T Id { get; set; }
}
This will ensure that you can compare Id properties correctly.
Secondly, in your LoadData() method, change the if statement to
if (T is IIdentifiable<T>)
{ // ^- here's the first problem
data = data.Where(d => _dataSource.All(ds => ((IIdentifiable<T) ds).Id != ((IIdentifiable<T) d).Id)).ToList();
}

Is it possible to make a template method that operates on a struct that has some known attributes

I have to structs both having e.g. "Id":
public struct User
{
public int Id;
public string Email;
}
public struct Computer
{
public int Id;
public string Name;
}
I'd like to make a template method to rewrite Id from one IList of Computers, Users and such to another.
I've tried below, but VS complains T does not contain a definition for Id:
private static void RewriteIListIds<T>(ref IList<T> pre, IList<T> post)
{
if (post != null && post.Count > 0)
{
Assert.IsTrue(pre != null && pre.Count > 0);
for (int i = 0; i < post.Count; i++)
{
T preElement = pre[i];
T postElement = post[i];
preElement.Id = postElement.Id;
pre[i] = preElement;
}
}
}
EDIT:
Interesting ideas but I probably should have mention I'm testing a service which I really don't want and most probably can't really change.
EDIT2:
Just for future references and to be more clear - I've probably made this problem more generic than it should be - User and Computer structs are what a Web Service (currently configured as SOAP) returns in an IList. [DataContract] and [Data Member] was removed from above example to make this problem a bit more generic.
No. C# generics aren't C++ templates, basically. I would suggest that:
You stop exposing fields publicly
You stop using mutable structs
You stop using ref when you don't need to (see my article on parameter passing for more details)
You extract an interface with a read/write Id property
You implement that interface on two classes for User and Computer
You add a constraint of where T : IFoo to your generic method where IFoo is your new interface (with a better name, of course)
You can then remove the pre[i] = preElement; line of your method too...
Meta: Don't refer to a field as an attribute; the word attribute has a very specific meaning in .NET which is not the same as a field or property.
(Apologies for the slightly curt response - I don't have time to explain each point in detail right now.)
I agree with Jon: you probably don't have to do this, and it can be done in some other way.
But if you really have to you can tell the method how the type gets or sets its id.
public delegate int IdGetter<in T>(T holder);
public delegate T IdSetter<T>(T holder, int newId);
private static void RewriteIListIds<T>(IList<T> pre, IList<T> post,
IdGetter<T> getId, IdSetter<T> setId)
{
if (post != null && post.Count > 0)
{
for (int i = 0; i < post.Count; i++)
{
T preElement = pre[i];
T postElement = post[i];
int id = getId(preElement);
postElement = setId(postElement, id);
post[i] = postElement;
}
}
}
To use it
RewriteIListIds<User>(aList, bList, u => u.Id, (u,id) => {u.Id = id; return u;});
I assume that you have a C++ background? The C# feature you are using is called "generics".
Generics are not templates.
[...] You can think of templates as a fancy-pants search-and-replace
mechanism. When you say DoIt<string> in a template, the compiler
conceptually searches out all uses of “T”, replaces them with
“string”, and then compiles the resulting source code. Overload
resolution proceeds with the substituted type arguments known, and the
generated code then reflects the results of that overload resolution.
[...] That’s not how generic types work; generic types are, well, generic.
We do the overload resolution once and bake in the result. We do not
change it at runtime when someone, possibly in an entirely different
assembly, uses string as a type argument to the method
On another note, it is strongly recommended not to create mutable structs in C#.
You need to constrain you generic so that the compiler knows something about type T.
One way to do this is to create a parent object that contains the Id value, lets call it Thing, then have your two objects inherit from that. Then you can declare your generic so that T is constrained to children of Thing:
public class Thing
{
public int Id;
}
public class User: Thing
{
public string Email;
}
public class Computer : Thing
{
public string Name;
}
private static void RewriteIListIds<T>(ref IList<T> pre, IList<T> post) where T: Thing
Now the compiler knows that T must contain all the properties of Thing so it can assume there will be an Id field. If you don't want to use inheritance, the you can do the same thing with an interface and have each of your objects implelment that interface.

Implementing a class from 2 interfaces that share some parts

Is the following not a good practice?
public interface IMyImmutableData
{
int Data { get;}
}
public interface IMyMutableData
{
int Data { set;get;}//implements both get and set
}
public class MyData : IMyImmutableData, IMyMutableData
{
public int Data{get;set;} //implements both IMyImmutableData, IMyMutableData
}
void Main()
{
MyData myData = new MyData{Data=10};
Console.WriteLine(myData.Data);
}
The reason I ask is that resharper gives me the following warning: "possible ambiguity while accessing by this interface"
The reason I want to do the above is that when I create methods that use the MyData class, I would like to send it either as IMyMutable or IMyImmutable objects, so that users of the method know that they can expect the method to update or not update the passed in object.
I think you can ignore resharper's warning, as the ambiguity is intentional.
However, usually a wrapper class is used to provide readonly access to something, that way it can't be cast to anything that does provide more functionality.
public class MyReadonlyData : IMyReadonlyData {
private MyData instance;
public int Data {
get {
return instance.Data;
}
}
public MyReadonlyData( MyData mydata ) {
instance = mydata;
}
}
// no access to original object or setters, period.
You need to make one or both of the implementations explicit:
public int IMyImmutableData.Data { get; }
public int IMyMutableData.Data { get; set; }
When you mark one as explicit, it can only be accessed when specifically cast as that type:
MyData obj = new MyData();
obj.Data; // Doesnt exist
(obj as IMyImmutableData).Data // Exists, specifically cast as this interface
If you choose to not mark one as explicit, it will be the property chosen when cast as other appropriate types.
I think in this case your structure is fine. You don't want to explicitly implement the interfaces via separate properties, because then the Data you access via the immutable interface will actually be different than that for the mutable interface.
Also, your actual code is likely more complex, because in this case there is no ambiguity: you are accessing Data via the object itself, so interfaces need not be considered.
One solution with explicit interface implementation would be to use a common backing field, rather than auto-properties:
private int _data;
public int IMyImmutableData.Data
{
get
{
return this._data;
}
}
public int IMyMutableData.Data
{
get
{
return this._data;
}
set
{
this._data = value;
}
}
You could cast the variable and tell the compiler what exactly you mean: (resolve ambiguity)
MyData myData = new MyData{Data=10};
Console.WriteLine( ((IMyMutableData)(myData)).Data );
You need a combined interface with a "new" qualifier on the read-write interface to avoid the squawk. Further, your interfaces are poorly named. Better names would be something like "IReadableData" and "IWritableData", and "IReadWriteData". Note that while "IReadableData" does not provide any means of mutating the data, that by no stretch of the imagination implies that the data is immutable. If something is immutable it won't every be changed by anyone; that would clearly not be the case with an object of type MyData.

Creating a Generic Class Member for Extra Info

I'm very new to C# (this is my first C# project). I'm fairly confident with the basics, but I'm starting to run into things that are raising issues that I can't quite solve, no matter how many different ways I Google it. A LOT of my questions have been answered by this site. :]
So, since I can't find the answer to this question, I decided to post it myself.
Maybe it's too basic of a question that everyone pretty much knows it, but I couldn't figure this out from the MSDN reading.
It has to do with C# Generics. I'm programming for a video game engine, and I've created a simple messaging system between AI units. The Message class contains members like sender, receiver, dispatchTime, and extraInfo. I want to use the extraInfo member to be a useful, flexible addition to the Message class, so I would like for it to be able to contain any type (an int node index, a double path cost, a relevant Vector3 position from XNA, etc, etc...). My research for this pointed me in the direction of Generics.
I figured out how to use Generics in something like a List, but I haven't read anything about how to just declare and implement a generic -member-. Just a single member, not a collection.
How would I declare this member, extraInfo? Additionally, when accessing it from another class, I would like to be able to type:
info = message.extraInfo;
..to retrieve the extra information via the get property.
How would this be done in C#?
Your message class would look something like this
public class Message<T>
{
public object Sender { get; set; }
public object Receiver { get; set; }
public T ExtraInfo { get; set; }
}
public static void Main()
{
Message<double> doubleMessage = new Message<double>() { ExtraInfo = 4.0d };
Message<string> stringMessage = new Message<string>() { ExtraInfo = "Hello World" };
}
Using .NET 4.0, you can make your ExtraInfo property of type dynamic. You could then store anything at all in it, and as long as you access it properly at runtime, you'll be ok.
You could declare the extraInfo member of your class as an object. You could then put anything you want in there.
You can solve your problem by creating an ExtraInfoType object that contains an
object as well as implicit operators to convert to and from the various object types transparently.
The ExtraInfoType object can also indicate what kind of object is stored in the ExtraInfoType.
An example of this implementation is below.
enum ExtraInfoKind
{
Integer,
Double
}
class ExtraInfoType
{
object value;
public object Value {
get { return value; }
}
ExtraInfoKind kind;
public ExtraInfoKind Kind {
get { return kind; }
}
private ExtraInfoType(object o, ExtraInfoKind kind){
this.value=o;
this.kind=kind;
}
public static implicit operator int(ExtraInfoType o){
if(o.kind!= ExtraInfoKind.Integer)
throw new InvalidCastException();
return (int)o.value;
}
public static implicit operator double(ExtraInfoType o){
if(o.kind!= ExtraInfoKind.Double)
throw new InvalidCastException();
return (double)o.value;
}
public static implicit operator ExtraInfoType(int o){
return new ExtraInfoType(o, ExtraInfoKind.Integer);
}
public static implicit operator ExtraInfoType(double o){
return new ExtraInfoType(o, ExtraInfoKind.Double);
}
}
/* Example
class Program
{
public static void Main(string[] args)
{
ExtraInfoType t=1;
Console.WriteLine(t.Kind);
int valueT=t;
Console.WriteLine(t);
Console.ReadLine();
}
}
*/
Here you would declare extraInfo under the type ExtraInfoType.
Note that no generics are necessary here. Note also that ExtraInfoType
can store only one kind of object, which can be determined by the Kind property.
If the object is cast to the wrong type, an InvalidCastException is thrown, as
can be seen in the implicit operators above.

Should a protected property in a C# child class hide access to a public property on the parent?

I have the following code:
public class Parent
{
public string MyField { get; set; }
}
public class Child : Parent
{
protected new int MyField { get; set; }
}
I try and access this with:
static void Main(string[] args)
{
Child child = new Child();
child.MyField = "something";
}
Visual studio 2008 compiles this without comment, but under Mono (2.4.2, Ubuntu) I get the error message
'HideTest.Child.MyField' is inaccessible due to its protection level (CS0122)
Is one implementation or the other more compliant with the standard here?
Edit: Thanks to all the people who have pointed out the bad design. Unfortunately it's a third-party library and changing it significantly isn't practical.
From ECMA-334 (the C# spec) §10.7.1.2 :
A declaration of a new member hides an inherited member only within the scope of the new member.
You can see this behavior by running this test on Microsoft's implementation.
using System;
using NUnit.Framework;
namespace ScratchPad
{
[TestFixture]
public class Class1
{
[Test]
public void InheritanceHiding()
{
var b = new Base();
var d = new Derived();
var baseSomeProperty = b.SomeProperty;
var derivedSomeProperty = d.SomeProperty;
b.GetSomeProperty();
d.GetSomeProperty();
}
}
public class Base
{
public string SomeProperty
{
get
{
Console.WriteLine("Getting Base.SomeProperty");
return "Base.SomeProperty";
}
}
public string GetSomeProperty()
{
return SomeProperty;
}
}
public class Derived : Base
{
protected new int SomeProperty
{
get
{
Console.WriteLine("Getting Derived.SomeProperty");
return 3; //Determined by random roll of the dice.
}
}
public new int GetSomeProperty()
{
return SomeProperty;
}
}
}
Which will output:
Getting Base.SomeProperty //(No Controversy)
Getting Base.SomeProperty //(Because you're calling from public scope and the new member is in protected scope, there is no hiding)
Getting Base.SomeProperty //(No Controversy)
Getting Derived.SomeProperty //(Now because you're calling from protected scope, you get the protected member).
So the property you're accessing from your Main() should be the base class property (as it is in MS.NET), not the derived property (as in Mono), because the new derived member only hides the 'old' base member in protected scope.
Mono is doing something wrong here according to the spec.
Jason's answer is correct but he asks for a justification of this behaviour. (Namely that a hiding method is only hiding within the scope of the hiding method.)
There are a number of possible justifications. One in particular is that this is yet another way in which the design of C# mitigates the Brittle Base Class problem.
FooCorp makes Foo.DLL:
public class Foo
{
public object Blah() { ... }
}
BarCorp makes Bar.DLL:
public class Bar : Foo
{
// stuff not having to do with Blah
}
ABCCorp makes ABC.EXE:
public class ABC
{
static void Main()
{
Console.WriteLine((new Bar()).Blah());
}
}
Now BarCorp says "You know, in our internal code we can guarantee that Blah only ever returns string thanks to our knowledge of our derived implementation. Let's take advantage of that fact in our internal code."
public class Bar : Foo
{
internal new string Blah()
{
object r = base.Blah();
Debug.Assert(r is string);
return (string)r;
}
}
ABCCorp picks up a new version of Bar.DLL which has a bunch of bug fixes that are blocking them. Should their build break because they have a call to Blah, an internal method on Bar? Of course not. That would be terrible. This change is a private implementation detail that should be invisible outside of Bar.DLL.
In general, the .NET implementation of C# should probably be considered "canon". From the documentation on the new Modifier:
A constant, field, property, or type introduced in a class or struct hides all base class members with the same name.
... it seems like the Mono implementation is more correct given this definition. It should be hiding the implementation of MyField in the Parent class, and therefore it should only be accessible with the int MyField signature from the Child class.
Prelude: This code is crazy. If you actually have code in your app like this, fix it now. Either make them both protected or both public!
Regarding the error: The CLR has a lot of really strange 'edge case' rules in it for dealing with things like this. The best place to look for this kind of stuff is usually Eric Lippert's blog.
In saying that though, it looks like mono is actually doing the more sensible thing here in my opinion.
On second look, the C# one makes more sense once you factor in the 'behind the scenes' stuff.
Properties are not "first class" in MSIL. A property in C# or VB is just compiled down to a get and set method (the compiler also sticks an attribute somewhere for bookkeeping).
int MyField { get; set; } will actually produce MSIL for two methods:
void set_MyField(int value);
int get_MyField();
Now, given that your new method has a different type, you'll end up with the following 2 setter methods.
void set_MyField(int value);
void set_MyField(string value);
When you call x.MyField = "string" you're just calling one of those methods. This then boils down to a normal method overloading scenario. It's perfectly valid to have two methods with the same name that take different parameters, so the compiler will just select the string one and carry on it's merry way.
So yeah. The C# one makes sense if you know how the internals work, the Mono one makes more sense if you don't.
Which one is "more correct"? Ask Eric Lippert :-)
Just adding my 2 cents) That's a Mono bug, here is the description.
IMHO the difference is that MS.NET recognize the type string for MyField and sets the value of Parent property and in Mono in just tries to access MyField in Child class.
You are making something that's available through the base class unavailable through the child. You can try that, but it won't actually do anything. People can always just do this:
Parent child = new Child();
and call the method. So if you want the field to be hidden, declare a new one and keep the inherited one public.

Categories

Resources