C# acess modifiers compilation error - c#

public List<ObjectA> ObjectAList
{
get
{
return ObjectAList ?? new List<ObjectA>();
}
set;
}
'ObjectAList.set' must declare a body because it is not marked abstract, extern, or partial
Why is that?

You are trying to mix Auto implemented property with normal property. Moreover you need a backing field, otherwise you will run in to Stackoverflow exception. Your property declaration should be like:
private List<ObjectA> _ObjectAList; //private backing field
public List<ObjectA> ObjectAList
{
get
{
return _ObjectAList ?? new List<ObjectA>();
}
set
{
_ObjectAList = value;
}
}

Thats how the langauge works.
You cant do partial explicit / implicit.
Its all or nothing.
When you do it implicitly it just writes to an auto generated backing field, but it wants to do both sides.
Moreover your get is going to have a stack overflow even if the set worked because you are going to call the get over and over with no base case to end the recursion.

Related

Can I define a custom getter for a C# auto-implemented property (a.k.a. auto backing field)?

Note: I know how to accomplish this without using auto-implemented properties, but I'm wondering if C# has a built-in way to do this.
Let's say I have this simple example of an auto-implemented property (a.k.a. auto backing field):
public class MyClass
{
public MyClass(){}
public string MyString { get; private set; }
}
Now, I would like to return a custom exception in the getter if the auto backing field is null:
public class MyClass
{
public MyClass(){}
public string MyString
{
get
{
return [backing field] ?? throw new Exception("MyString is null");
}
private set;
} = null;
}
Do newer C# versions support something like this? Perhaps there is some syntactic sugar that I can use in place of [backing field] to access the backing field that is automatically created by the compiler?
Note on putting an exception in the getter: I know it shouldn't be a habit. But Microsoft does it occasionally; for example, the property HttpContext.Request.Form will throw an exception if the request is not of the proper content-type.
No, you can not access to backing field in this way.
You must define backing field and validate it.
public class MyClass
{
public MyClass(){}
private string? _myString
public string MyString
{
get
{
return _myString ?? throw new Exception("MyString is null");
}
private set => _myString = value;
} = null;
}
As Fred said, its better to validate it outside of property.
I'm surprised noone mentioned the field keyword, it is exactly what you are asking for (what you would use instead of [backing field] in your example). It was supposed to be shipped with C# 10. It seems it is going to be shipped with C# 11 instead (?)
Search for Field Keyword here.
Put validation in the setter and/or ensure that the constructor sets a valid/non-null default value.
Or make the property nullable to hint to the customer that they have to account for a null value possibility.
Alternatively (but less optimally for multiple reasons), make the property private and add a method for accessing it.
Strongly advise against a property get directly throwing an exception. You or the consumer will dislike the results at some point.

c# property setter body without declaring a class-level property variable

Do I need to declare a class-level variable to hold a property, or can I just refer to self.{propertyname} in the getter/setter?
In other words, can I do this? (where I haven't defined mongoFormId anywhere):
public string mongoFormId
{
get
{
return this.mongoFormId;
}
set
{
this.mongoFormId = value;
revalidateTransformation();
}
}
You can either use automatic accessors or implement your own. If you use automatic accessors, the C# compiler will generate a backing field for you, but if you implement your own you must manually provide a backing field (or handle the value some other way).
private string _mongoFormId;
public string mongoFormId
{
get { return this._mongoFormId; }
set
{
this._mongoFormId = value;
revalidateTransformation();
}
}
UPDATE: Since this question was asked, C# 6.0 has been released. However, even with the new syntax options, there is still no way to provide a custom setter body without the need to explicitly declare a backing field.
You need to set a field variable and store the value there, if you're going to use custom getter and setter.
With the code you have right now you will be running into a stack overflow exception. When you assign something to mongoFormId, you'll execute the line this.MongoFormId = value;. This is an assignment to mongoFormId, resulting in executing the line this.MongoFormId = value;, and so on. It won't ever stop.
The correct way is a field:
private string _mongoFormId;
public string mongoFormId {
get { return this._mongoFormId; }
set {
this._mongoFormId = value;
revalidateTransformation();
}
}
You should have a backing variable. Take a closer look:
get { return this.mongoFormId; }
Is going to call the getter on mongoFormId, which will call that code again, and again, and again! Defining a backing variable will avoid the infinite recursive call.
Check MSDN Properties Overview
While a property definition generally includes a private data member,
this is not required. The get accessor could return a value without
accessing a private data member. One example is a property whose get
method returns the system time. Properties enable data hiding, the
accessor methods hide the implementation of the property.
You can do it both the ways.
If you want to have a class level member variable then do it this way -
public class sampleClass
{
private string _mongoFormId;
public string mongoFormId {
get { return _mongoFormId; }
set {
_mongoFormId = value;
revalidateTransformation();
}
}
}
Or do this simple in class, if no need for revalidateTransformation() execution call there
public class sampleClass
{
public string mongoFormId {get; set;}
}
This won't work since you get a recursive call to the property.
If I'm not mistaken, the result will be a StackOverflowException.
You must use a variable.
private string mongoFormId;
public string MongoFormId
{
get
{
return this.mongoFormId;
}
set
{
this.mongoFormId = value;
revalidateTransformation();
}
}
If you don't have to execute revalidateTransformation, you can use the auto-property.
This will create a backingfiled for you behind the scene.
public string MongoFormId { get; set; }
With the code you wrote, you are creating a recursive endless loop on both the get and set. The this keyword refer to the current class, not the property you are in.
So yes, you need to declare a private field. And to avoid confusion, create properties following the MSDN Naming Guideline (Use Pascal case for properties, camel case for private fields). And please do the same for your methods, it should be RevalidateTransformation instead of revalidateTransformation if you follow the C# convention instead of java's.
private string mongoFormId;
public string MongoFormId
{
get
{
return mongoFormId;
}
set
{
mongoFormId = value;
RevalidateTransformation();
}
}
public string mongoFormId {
get {
return this.mongoFormId;
}
set {
this.mongoFormId = value;
revalidateTransformation();
}
}
this way you have the Function recursive on all paths
The only way i see is to use a private data member. As other boys tells.

properties in C#

Why are we able to write
public int RetInt
{
get;set;
}
instead of
public int RetInt
{
get{return someInt;}set{someInt=value;}
}
What is the difference between the two?
This feature is called Auto implemented properties and introduced with C# 3.0
In C# 3.0 and later, auto-implemented properties make
property-declaration more concise when no additional logic is required
in the property accessors. They also enable client code to create
objects. When you declare a property as shown in the following
example, the compiler creates a private, anonymous backing field
that can only be accessed through the property's get and set
accessors.
class Customer
{
// Auto-Impl Properties for trivial get and set
public double TotalPurchases { get; set; }
public string Name { get; set; }
public int CustomerID { get; set; }
For your question
What is the difference between the two?
In your case, none. Since you are not doing anything while setting or retrieving the value, but suppose you have want to do some validation or want to perform other types of check then :
private int someInt;
public int RetInt
{
get
{
if (someInt > 0)
return someInt;
else
return -1;
}
set { someInt = value; } // same kind of check /validation can be done here
}
The above can't be done with Auto implemented properties.
One other thing where you can see the difference is when initializing a custom class type property.
If you have list of MyClass
Then in case of Normal property, its backing field can be initialized/instantiated other than the constructor.
private List<MyClass> list = new List<MyClass>();
public List<MyClass> List
{
get { return list; }
set { list = value; }
}
In case of Auto implemented property,
public List<MyClass> SomeOtherList { get; set; }
You can only initialize SomeOtherList in constructor, you can't do that at Field level.
How are these two different ?
There are different at least by 2 points:
In normal property you have to define a field before (someInt in your case)
In normal property you can set a breakpoint into the set/get modifiers, instead in auto property can not do that.
In other words: if you need "just property", use auto-properties, if you need more control over workflow (raise an event on set, debug, run other stuff inside), use "normal" properties.
These are auto implemented properties. Please see http://msdn.microsoft.com/en-us/library/bb384054.aspx for more info.
Basic reason why these were introduced was to reduce the overhead of programmer of creating a private variable like someInt which had little use than being used in a property.
Actually these aren't really different, in both cases you have a private field that corresponds to your property, but in the first case it is generated by the compiler and hidden.
If you need to use the variable behind the property quite often in your class, I think it's better to declare your property the old way (2nd one), because each time you will access it this will call the getter if you do it the "new" way.
If you only need it to be used from outside your class (or in most of cases), then you can go with the "new" way (1st one)

Do C# properties hide instance variables or is something deeper going on?

Consider the class:
public class foo
{
public object newObject
{
get
{
return new object();
}
}
}
According to MSDN:
Properties are members that provide a flexible mechanism to read,
write, or compute the values of private fields. Properties can be used
as though they are public data members, but they are actually special
methods called accessors. This enables data to be accessed easily
And:
Properties enable a class to expose a public way of getting and
setting values, while hiding implementation or verification code.
A get property accessor is used to return the property value, and a
set accessor is used to assign a new value. These accessors can have
different access levels. For more information, see Accessor
Accessibility.
The value keyword is used to define the value being assigned by the
set indexer.
Properties that do not implement a set method are read only.
while still providing the safety and flexibility of methods.
Does this therefore mean that at some point in time the value of the newObject property has a reference to the returned new object?
edit removed readonly from property
edit2 also would like to clarify that this is not the best use for a property but its done to try and illustrate the question more effectively.
You return a new object on each access to the property and that is not the expected behavior of properties. Instead you should return the same value each time (e.g. a value stored in a field). A property getter is simply glorified syntax for a method that returns a value. Your code compiles into something like this (the compiler creates a getter by prefixing the property name with get_ which is then emitted as IL):
public class foo
{
public object get_newObject()
{
return new object();
}
}
Each call to the getter will create a new object that foo doesn't know about or has access to.
Does this therefore mean that at some point in time the value of the newObject property has a reference to the returned new object?
No.
Property using a backing field:
class Foo {
readonly Object bar = new Object();
public Object Bar { get { return this.bar; } }
}
Using automatic properties:
class Foo {
public Foo() {
Bar = new Object();
}
public Object Bar { get; private set; }
}
A property is accessed using the same easy syntax as a public field. However, by using a property you can add code to the getter and the setter allowing you to do stuff like lazy loading in the getter or validation in the setter (and much more).
Under the hood, your property will simply be calling a function named get_newObject() that looks like this:
public object get_newObject()
{
return new object();
}
Since that is the case, it will always return a new object every time it is invoked.
If you want to retain a reference to the object, then I would recommend creating a private field to hold the data and having the property access that field, like so:
private object myObject;
public object newObject
{
if(myObject == null)
{
myObject = new object();
}
return myObject;
}
Since your property doesn't define set, and your field is private, newObject is basically eradonly outside of the containing class.
Properties in C# are "syntactic sugar". The code within the get block of a property is in fact put into a hidden get_PropertyName() method, and the set block into a hidden set_PropertyName() method. In the case of your code, the following method will be created:
public object get_newObject()
{
return new object();
}
You can see these hidden methods if you view the compiled assembly using Reflector, or ildasm.
When the property is used, the C# compiler converts any "get" accesses of your property into calls of the get_newObject() method. As an example:
If you were to write the following:
var foo = new foo();
var aNewObject = foo.newObject;
The compiler would convert that to:
var foo = new foo();
var aNewObject = foo.get_newObject();
So, in answer to your other question, the newly created object returned when someone "gets" the property won't be stored within your foo instance, the caller will simply get a new object every time.
Not exactly. Properties are just syntactic sugar so that you don't have to write accessor methods (like Java).
So this:
private int _myInteger;
public int MyInteger
{
get { return _myInteger; }
set { _myInteger = value; }
}
is equivilant to this:
private int _myInteger;
public int GetMyInteger()
{
return _myInteger;
}
public void SetMyInteger(int value)
{
_myInteger = value;
}
and it gets better with this, which is also equivilant:
public int MyInteger { get; set; }

Auto-implemented properties and additional function

Is there a way to do something like this in C#:
public class Class2 {
public string PropertyName1 { get
{
return this; //i mean "PropertyName1"
}
set {
this = value;
DoAdditionalFunction();
}
}
Because I need to call additional function in the "set" I need to have an extra private field like
private string _propertyName1;
public string PropertyName1 { get
{
return _propertyName1;
}
set {
_propertyName1= value;
DoAdditionalFunction();
}
I don't want to use additional property like _propertyName1. Is there a way to accomplish this or any best practices?
No - if you need any behaviour other than the most trivial "set a field, return the field value", you need to write "full" properties. Automatically implemented properties are only a shorthand for trivial properties.
Note that you haven't really got an "extra" private field, in terms of the actual contents of an object - it's just that you're explicitly declaring the private field instead of letting the compiler do it for you as part of the automatically implemented property.
(It's not clear what your first property is trying to do - setting this in a class is invalid, and you can't return this from a property of type string unless you've got a conversion to string...)

Categories