I've come across a strange behaviour in .NET/Reflection and cannot find any solution/explanation for this:
class A
{
public virtual string TestString { get; set; }
}
class B : A
{
public override string TestString
{
get { return "x"; }
}
}
Since properties are just pairs of functions (get_PropName(), set_PropName()) overriding only the "get" part should leave the "set" part as it is in the base class. And this is just what happens if you try to instanciate class B and assign a value to TestString, it uses the implementation of class A.
But what happens if I look at the instantiated object of class B in reflection is this:
PropertyInfo propInfo = b.GetType().GetProperty("TestString");
propInfo.CanRead ---> true
propInfo.CanWrite ---> false(!)
And if I try to invoke the setter from reflection with:
propInfo.SetValue("test", b, null);
I'll even get an ArgumentException with the following message:
Property set method not found.
Is this as expected? Because I don't seem to find a combination of BindingFlags for the GetProperty() method that returns me the property with a working get/set pair from reflection.
EDIT:
I would expect that behaviour if I'd use BindingFlags.DeclaredOnly on GetProperties() but the default (BindingFlags.Default) takes inherited members into account and the setter of TestString clearly is inherited!
Here's a workaround:
typeof(B).GetProperty("TestString")
.GetAccessors() // { B.get_TestString() }
.First() // B.get_TestString()
.GetBaseDefinition() // A.get_TestString()
.DeclaringType // typeof(A)
.GetProperty("TestString") // A.TestString: CanRead and CanWrite
This approach should be reasonably robust. You will need to be more careful with this (BindingFlags) if you're looking for non-public accessor(s).
EDIT:
Note that this approach is different from "hardcoding" typeof(A).GetProperty("TestString") or typeof(B).BaseType.GetProperty("TestString") because it finds the actual, original type that declares the property in question. Since it isn't possible (not in C# at least) for a derived type to add new accessors to an overridden property, the property-declaration on this "original" type should contain all the relevant accessors.
You're not overwritting a method, you're overwritting a property definition
The default definition of the property includes Get/Set methods, and your new definition only includes a Get method, so it makes sense that your overwritten property only has Get available, not Set
Edit
If you run something like Reflector on this, you'll see that
class A
{
public virtual string TestString { get; set; }
}
class B : A
{
public override string TestString
{
get { return "x"; }
}
}
compiles into something like that looks like
internal class A
{
// Fields
[CompilerGenerated]
private string <TestString>k__BackingField;
// Methods
public A();
// Properties
public virtual string TestString { [CompilerGenerated] get; [CompilerGenerated] set; }
}
internal class B : A
{
// Methods
public B();
// Properties
public override string TestString { get; }
}
When you set the value in code, you are actually calling something like B.base.set_TestValue. When you reflect something, you are trying to find B.set_TestValue, which doesn't exist.
While true that you cannot overwrite a property, you can overwrite a property definition (providing it doesn't conflict with the base property definition). Since your question was originally tagged with WPF, I was thinking of DependencyProperties at the time, which are actually property definitions, and not properties in the sense that you might be thinking of.
Related
How come you can set a get-only auto-property from a constructor? The code below shows how you can set the property from the constructor but using reflection shows that there really isn't a setter behind the scenes. How does it get set from the constructor call if the setter method doesn't even exist in the IL?
void Main()
{
var obj = new GetOnlyProperty("original value");
Console.WriteLine(obj.Thing); //works, property gets set from ctor
//get the set method with reflection, is it just hidden..?
//nope, null reference exception
typeof(GetOnlyProperty)
.GetProperty("Thing", BindingFlags.Instance | BindingFlags.Public)
.GetSetMethod()
.Invoke(obj, new object[]{"can't set me to this, setter doen't exist!"});
}
public class GetOnlyProperty
{
public string Thing { get; }
public GetOnlyProperty(string thing)
{
Thing = thing;
}
}
A read-only automatically-implemented property is converted by the compiler into a read-only field and a read-only property. Assignments to the property in the constructor are compiled as assignments to the underlying field.
So your code here:
public class GetOnlyProperty
{
public string Thing { get; }
public GetOnlyProperty(string thing)
{
Thing = thing;
}
}
is compiled into IL as if you'd written:
public class GetOnlyProperty
{
private readonly string _thing;
public string Thing => _thing;
public GetOnlyProperty(string thing)
{
_thing = thing;
}
}
... except that _thing is really given an "unspeakable name" that wouldn't be a valid C# identifier.
A read-only property (get only) has a backing readonly field, which as you probably know, can only be set in the constructor.
hence when you have object Property { get; }
this translates to
private readonly object _property;
public object get_Property(){return _property;}
and the compiler knows that if you set the property in the constructor to set the field directly
Because a read-only property should be assigned at a time or another, otherwise its value would always be the default value of the type, and it would be completely useless.
This is what constructors are for (beside other obvious reasons), to assign values to read-only fields.
For an object sellprint declared as static in the class
private static string sellprint = "";
public string Sellprint
{
get { return sellprint; }
}
public void SetSellprint(string x)
{
sellprint = x;
}
How is this
different from
public string Sellprint
{
get; set;
}
internally.
I could not find any examples of code 1 on msdn. what does it translate into?
The compiler creates a getter method for your property in the first code that returns the value of sellprint field because you implement only the getter method.In the second code, both getter and setter methods creating by compiler and also the backing-field.That's the difference.
You can verify that using ILDASM.exe:
First, consider this code:
class Foo
{
private string _value;
public string Value
{
get { return _value; }
}
public void SetValue(string str)
{
_value = str;
}
}
As you can see there is only one method generated by compiler which is get_Value.
If we change it like this and make the Value an auto-implemented property:
class Foo
{
public string Value { get; set; }
}
You can see that compiler creates both getter (get_Value) and setter (set_Value) method and also create a private backing field for the property.
There is no pros or cons about the functionality except in the second code you are doing the same work with less code.
1) should not work because there is no sellprint - assuming you have a field named sellprint and just forgot in your code snippet, you provide a get accessors and a method instead of the set accessors, which is kinda strange.
2) will create the field required automatically (and will not tell you the name, so you cannot accidentally use it)
There is not difference between those two though.
My code is returning a blank array of PropertyInfo
PropertyInfo[] classProperties = typeof(Processor).GetProperties();
All properties in this class are public.
Using .NET 2.0 Framework.
I have also tried using an instance declared earlier in my code:
PropertyInfo[] classProperties = Computer.Processor[0].GetType().GetProperties();
And I have tried using bindings such as Default, Instance and Public.
Any ideas?
The parameterless form will return public properties. So there are 2 likely options:
they are not properties (but instead, fields)
they are not public
A public property is something a: with the public modifier, and b: with a get or set accessor, for example either of:
public int Foo {get;set;} // automatically implemented property
public string bar;
public string Bar { // manually implemented property
get { return bar; }
set { bar = value; }
}
Note also that interface-bound properties that are implemented as explicit interface implementation will only be reflected if you query against the interface, not the class; so the following will not show unless you start from typeof(ISomeInterface):
string ISomeInterface.Bar { get { return someValue; } }
What is the best practice to create pre-initialized class. For example
Chip chip = new Atmega8();
I would like to have its properties already defined like:
chip.Name = "Atmega8 AVR Chip";
and so on.
How to achieve it in C#?
Should I use readonly public properties or property with private set?
Have your constructor initialize the values:
class Atmega8 {
public Atmega8 ()
{
Name = "Atmega8 AVR Chip";
}
public string Name { get; set; }
}
If you intend Name to be the same for all instances, it might make sense to declare it abstract in the base class and override the getter:
abstract class Chip {
public abstract string Name { get; }
}
class Atmega8 : Chip {
public override string Name {
get { return "Atmega8 AVR Chip"; }
}
}
Because we haven't defined a set method, the value cannot be changed, much like a readonly variable except it isn't even stored anywhere and just returned on each call.
If you want the compiler to enforce that nothing can change the value of the field once initialized, then set it up as a read-only field, and populate it in the constructor of the class (or simply initialize it when you declare it; this doesn't work so well with inheritance though). If you don't care as long as nothing OUTSIDE the object can change it (meaning you will trust your own coding discipline to ensure it doesn't change internally), a get-only property with a backing field, or an auto-property with a private setter, are your bets.
IF you absitively posolutely DO NOT WANT the value to change for a particular class, EVER, then I would make it a get-only property returning either a string literal or a constant. I would recommend using the constant over the literal, as you can put the constants into their own static class which you can then use separately from each Chip class.
HOWEVER, there's a quirk of constants you should know. A constant value in .NET is stored in the manifest of not only the assembly containing the declaring code, but in every assembly that references the declaring assembly. Each assembly's code them uses the value from its own manifest. So, if the constant value EVER changes, any assembly that references the declaring assembly must be recompiled to update those assemblies' manifests with the new value. Otherwise, the constant will only have its new value when used from within the declaring assembly. For this reason, labeling a variable as constant should not be done lightly. Personally, my opinion is if the constant isn't some value on which the continued existence and functioning of the universe depends, like pi, e, the speed of light in a vacuum, Plank's Constant, Avogadro's Number, etc, then it isn't "constant". Anything else, like communication code ordinals, CAN change, even if doing so would break compatibility with every previous version of your program.
Depends what you want to accomplish.
It looks like you never want the value of Name to change. One approach would be to declare Name as abstract in Chip, and implement Name in each child class to return a constant string value.
abstract class Chip
{
public abstract string Name { get; }
}
class Amiga8 : Chip
{
public override string Name { get { return "Atmega8 AVR Chip"; } }
}
class Program
{
static void Main(string[] args)
{
Chip chip = new Amiga8();
Console.WriteLine(chip.Name);
}
}
In the constructor of the Atmega8 class you can set a property to something. Ie:
public Atmega8() {
Name = "Atmega8 AVR Chip";
}
If you do not want that to be changed in runtime you could mark the property as readonly ( only assignable through a constructor of declarative ).
private readonly string _Name = string.Empty;
public string Name {
get { return _name; }
}
public Atmega8() {
_Name = "Atmega8 AVR Chip";
}
Value of property cannot change -> Read-only public property.
Value of property can change -> Property with private set
If you don't want it to change, make the Name property a const or readonly on the Atmega8 class. Private set still allows the Name to change internally.
You're saying that you want the class to be populated at the same time it's initialized? Just populate the object in the constructor, like so:
class Test
{
public Test()
{
this.Name = "Hello World";
}
//if you need to pass information into the constructor:
public Test(string testName)
{
this.Name = testName;
}
}
Then, you can do this to initialize it:
Test test = new Test(); //default name of Hello World!
OR
Test test = new Test("Bingo!");
Today, I was cleaning up some of my code with FXCop and it complained about a Attribute class I had with this violation.
CA1019: Define accessor for attribute argument.
On this page, http://msdn.microsoft.com/en-us/library/ms182136.aspx there is more information, but I still do not get the reason for this as it seems to me more verbose and less relevant.
It gives two codes samples.
using System;
namespace DesignLibrary
{
// Violates rule: DefineAccessorsForAttributeArguments.
[AttributeUsage(AttributeTargets.All)]
public sealed class BadCustomAttribute :Attribute
{
string data;
// Missing the property that corresponds to
// the someStringData parameter.
public BadCustomAttribute(string someStringData)
{
data = someStringData;
}
}
// Satisfies rule: Attributes should have accessors for all arguments.
[AttributeUsage(AttributeTargets.All)]
public sealed class GoodCustomAttribute :Attribute
{
string data;
public GoodCustomAttribute(string someStringData)
{
data = someStringData;
}
//The constructor parameter and property
//name are the same except for case.
public string SomeStringData
{
get
{
return data;
}
}
}
}
I don't understand why the SomeStringData property is required. Isn't the someStringData a parameter? Why does it need to have its own property if it is already stored in another property?
Actually, mine is a little different as it looks like this.
[AttributeUsage(AttributeTargets.Property)]
public sealed class ExampleAttribute : Attribute
{
public ExampleAttribute(string attributeValue)
{
this.Path = attributeValue;
}
public string Name
{
get;
set;
}
// Add to add this to stop the CA1019 moaning but I find it useless and stupid?
public string AttributeValue
{
get
{
return this.Name;
}
}
}
Rather than a private field, I have used a public autoproperty, I had to add the last part to make the warning stop but I don't see the point and it also adds another public field to this class, which is redundant, and seems less clean.
That said, I assume that this warning is raised for a reason so what good reason I am missing here?
Thanks in advance.
FxCop is complaining because your existing property doesn't match the parameter name.
Therefore, it doesn't realize that the parameter actually is exposed.
You should rename the property or parameter to match (except for case), or suppress the warning.
FxCop rule CA1019 is just enforcing the .Net Framework coding guidelines for Attributes.
Use named arguments (read/write properties) for optional parameters. Provide a read/write property with the same name as each named argument, but change the case to differentiate between them.
Documentation Link: http://msdn.microsoft.com/en-us/library/2ab31zeh(v=vs.71).aspx
The reason behind the FxCop warning is that every piece of data you pass into the attribute's constructor should be made publicly available to access when the attribute instance is being retrieved by Reflection.
Let's say you have this:
[BadCustom("My String Data")]
public class DecoratedClass
{
}
How will you get "My String Data" back from that attribute instance when you read it using:
BadCustomAttribute attr = typeof(DecoratedClass)
.GetCustomAttributes(typeof(BadCustomAttribute), false)
.Single() as BadCustomAttribute;
Now you have the instance of your attribute, but no way to read the string passed into the constructor because you didn't at least declare a read-only property for it.
the idea is that you should write just:
[AttributeUsage(AttributeTargets.Property)]
public sealed class ExampleAttribute : Attribute
{
public ExampleAttribute(string attributeValue)
{
this.AttributeValue = attributeValue;
}
public string AttributeValue
{
get;
set;
}
}
This violation will also be thrown when the parameter name matches the property name, but the data types are different.