I want a dynamic static field - c#

I've got a class A with a public field b
class A
{
public static string b;
}
but now I want to make b dynamic so I call it anything. So I can make the class a DynamicObject
class A : DynamicObject
{
}
but I the compiler doesn't let me now call A.dynamicThing cos I have to instantiate A as dynamic.
How can I mangle c# further to make this work?

I don't belive you're going to find a way to make this work. It's not just the DynamicObject that makes things work. The declaration as a variable of the "dynamic" data type is what tells the compiler to actually use the DynamicObject base to resolve the member access. With static access direct to the class, you don't have that. So I really just don't think this is going to work in C# unless that changes in the future.

It's not possible right now with .NET 4
more information in this article.

I think I understand now - the closest you can get is by using an ExpandoObject :
dynamic foo = new ExpandoObject();
foo.somethinghere = "bar";
foo.dynamicThing = "baz";
Edit:
I don't think its possible to re-route the access to a static property of a class
to an expando object if the name of the property does not match - how would the compiler know that that's what you meant to do? You are getting a compile time error after all, not a runtime error.
From MSDN:
When a field, method, property, event,
operator, or constructor declaration
includes a static modifier, it
declares a static member. In addition,
a constant or type declaration
implicitly declares a static member.
Static members have the following
characteristics:
When a static member M is referenced in a member-access (Section 7.5.4)
of the form E.M, E must denote a type containing M.
...

public class FakeDynamicMethodInvoker : DynamicObject
{
// your code here
}
public class FakeDynamicWrapper<T>
{
static FakeDynamicWrapper()
{
DynamicStaticField = (dynamic)new FakeDynamicMethodInvoker();
}
public static T DynamicStaticField{ get; set; }
}
public class RealClassWithDynamicStaticField: FakeDynamicWrapper<dynamic>
{
}
somewhere in a code:
RealClassWithDynamicStaticField.DynamicStaticField.AnyMethod();

C# doesn't let you really rename variables to some dynamic name at runtime. Your question is mangled.
If you are wanting variable b to have a dynamic object at runtime, then use the dynamic keyword.
Example:
dynamic b = GetBValue();
b.SomeOperation(); // the type of "b" will be evaluated/chosen at runtime.

Old question but worth to answer :)
Static constructors are the answer to these problems.
https://msdn.microsoft.com/en-us/library/k9x6w0hc.aspx
public class MyClass
{
public static dynamic StaticDynamicObject;
static MyClass()
{
StaticDynamicObject = new ExpandoObject();
StaticDynamicObject.Prop = "woohoo!";
}
}

Related

Function Declarations with Generics in C#

I have a function that is declared like so:
public static string MultiWhereToString(List<WhereCondition<T>> whereConditions)
I am trying to pass it a variable called whereAnd which is delcared like so:
private List<WhereAndCondition<T>> whereAnd = new List<WhereAndCondition<T>>();
WhereAndCondition is a sub class of WhereCondition. It is declared like so:
public class WhereAndCondition<T> : WhereCondition<T>, IConditional where T : DatabaseObject
My issue is, if I try to execute the following code:
private List<WhereAndCondition<T>> whereAnd = new List<WhereAndCondition<T>>();
MultiWhereToString(whereAnd);
I get the following error:
Error 3 Argument 1: cannot convert from 'System.Collections.Generic.List<BrainStorm.WhereAndCondition<T>>' to 'System.Collections.Generic.List<BrainStorm.WhereCondition<T>>'
Any ideas on why? I think it has to do with the generics of the WhereCondition classes.
I would suggest using interfaces:
public static string MultiWhereToString(IEnumerable<ICondition<T>> whereConditions)
This would allow you a lot more freedom when calling this method.
Given:
class A {}
class A : B {}
An object of List<B> is not an instance of List<A>. So you can't cast a List<WhereAndCondition> to a List<WhereCondition>. You could use:
MultiWhereToString(whereAnd.OfType<WhereCondition>().ToList());
(There might also be a solution involving the in and out variance annotations, but I'm not terribly familiar with them.)
Your function is defined as taking a WhereCondition List, but you're passing it a WhereAndCondition List:
MultiWhereToString(List<WhereCondition<T>> whereConditions)
private List<WhereAndCondition<T>> whereAnd = new List<WhereAndCondition<T>>();
MultiWhereToString(whereAnd);
List variance has limited supported in .NET 4. See this question.
You can replace the entire WhereCondition<T> in your MultiWhereToString method with another generic type which is restricted to WhereCondition<T>.
Replace:
public static string MultiWhereToString(List<WhereCondition<T>> whereConditions)
With:
public static string MultiWhereToString<TType>(List<TType> whereConditions) where TType: WhereCondition<T>
Or alternatively change:
private List<WhereAndCondition<T>> whereAnd = new List<WhereAndCondition<T>>();
to:
private List<WhereCondition<T>> whereAnd = new List<WhereCondition<T>>();
And let inheritance take care of the rest for you.
This appears to be a covariance / contravariance issue.
Simplified to this:
public class WhereCondition
{
}
public class WhereAndCondition : WhereCondition
{
}
public class blah
{
public static void Blah()
{
List<WhereAndCondition> whereAnd = new List<WhereAndCondition>();
MultiWhereToString(whereAnd);
}
public static string MultiWhereToString(List<WhereCondition> whereConditions)
{
return null;
}
}
It's not going to work, because the list of WhereAndConditions can't be cast to List of WhereConditions:
Imagine it this way. You've got a list of giraffes, and the method is asking for a list of animals.
Without knowing what they are going to do with the list animals (like try adding a horse) the types are incompatible, but if you change it to something like this:
public static string MultiWhereToString(IEnumerable<WhereCondition> whereConditions)
{
return null;
}
Then the variance can kick in, and give you what you're looking for.
Generics have to be known explicitly at compile time because they are generated.
Why not use:
private List<WhereCondition<T>> whereAnd = new List<WhereCondition<T>>();
So you can still add WhereAndCondition objects to whereAnd.

Not able to specify the public variable class

I have a problem with the var keyword
I have defined it like this at the form load
public partial class form1 :form
{
public var a;
private void form1_load(object sender, eventargs e)
{
// i have used "a" like this....
a = abc.members blahhhh blahhhhh
bindingsource1.datasource = a;
datagridview1.datasource = bindingsource1;
}
}
but I got the error on this line
public Var a;
the type or namespace name 'var' could not be defined
Can I define public class varaible so that I can access this all methods in that class?
var in C# is different from var in other languages; in C# you use var to have the compiler determine the type of a certain local variable for you, but you cannot use it to declare fields/properties.
You have to specify the actual type instead. I have no idea what a is, so I can't tell you what type to use.
You have to use the concrete type instead of var - for example "string", "int", ...
This is because "var" is only syntactic suggar. The compliler interferes the concrete type and insert it instead of var. In your case this is impossible, because the compiler won't look so far as the form_load - it just looks at the expression after the "="
As a side note: you should not define fields as public. Make them private and define public accessors or public propertys for them. In this way you don't leak internal implementation details to the outside world and got no problems if you want to change this implementation-details later on.
If you want to make it a public (and not a local) variable you have to declare it as a specific type, for example 'string', 'int' or a selfwritten class
variables having an implicit type var must be declared at method scope.
public int a; would suffice, i suppose.
As per,
http://msdn.microsoft.com/en-us/library/bb383973.aspx
Only variables that are declared at method scope can have an implicit type var
As you need this for a linq query, you can assign the explicitly typed public variables wherever (inside a function) you run the query. For example,
func()
{
var results = from p1 in phones where p1.name="abc";
MyPublicVariable = results;
}
Where MyPublicVariable could be an enumerable.

C# What is the difference between creating a static object outside a class VS creating it inside a class?

I want to understand the difference between 3 sets of snippets below:
private static FirstObject o = new FirstObject();
public class ClassA
{
}
//-----------------------------------------------------
public class ClassA
{
private static FirstObject o = new FirstObject();
}
//-----------------------------------------------------
public class ClassA
{
private static FirstObject o;
public ClassA
{
o = new FirstObject();
}
}
Please help me understand in terms of scope, memory, performance and usage of these.
Thank you.
Invalid, as you can't have a variable outside of object
The proper way - the class has a static member, which is initialized when the class is accessed for the first time
Very bad, because every time when new object is created the static object will be recreated.
The first option will not compile. A static variable in C# must be scoped to a class or struct.
The second option is the preferred mechanism.
The third option is wrong because this creates a new FirstObject each time an instance of ClassA is created, which is almost certainly not what you want.
A fourth option would be to leverage a static constructor, e.g.,
public class ClassA
{
private static FirstObject o;
static ClassA
{
o = new FirstObject();
}
}
This option is useful if there is some special construction constraints for FirstObject. In this example, though, choose option 2 over option 4. Just know that option 4 exists.
Three cases below...
Assuming a typo here missing some outer construct... "o" is declared so that it will be globally accessible, as a single object, to the entire application. It will have one common set of all properties and data. It can be access directly by "Namespace.o"
"o" is declared so that it will be globally accessible, as a single object, to the entire application, However it is only accessible through another defined instance of "ClassA". Each separate instance of ClassA will have the same, single "o" object with the same properties and data.
This doesn't look right to me, I'm assuming "ol" is supposed to "o;". Even with this the code looks like its missing something. if the Line "o = new FirstObject" is correct it is not accessible in this fashion.

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.

How can I port this Java code to C#?

I am looking at a pattern implemented in Java and have some questions about how it aligns to (can be ported to) C#.
Java:
class Foo
{
private Class someClass;
...
}
class Bar
{
private Field some Field;
}
First, Class stores an instance of a domain object. It looks like Java exposes reflection methods on the type which are used to access fields on the object through reflection. What would type would be synonymous in C#? Would I use object and then use MethodInfo or is there a better way?
Second, Field is type in the framework and is assigned by using:
someClass.getDeclaredField(fieldName)
Is there a parallel in the .NET framework i should use?
Right now I created a custom object in place of the Class in Foo, and I created a custom object for Field. Is there a preferred way to do this?
You may take a look at the FieldInfo type and GetField method.
Code might look something among the lines:
class Foo
{
public Type someClass;
...
}
class Bar
{
private FieldInfo some_Field;
public Assign(string fieldName)
{
Foo foo = new Foo();
some_Field = foo.someClass.GetField(fieldName);
}
}
You may also get the value of the field by using:
foo.GetType().GetField("name").GetValue(foo).ToString()
In this example, we assume class foo has a field named "name". What does this help? Well think it as this way:
private string getValueOfUnknownField(string fieldName)
{
return(foo.GetType().GetField(fieldName).GetValue(foo).ToString());
}
Even if you change class foo and add new fields to it, you don't need to change getValueOfUnknownField method.

Categories

Resources