It might look foolish but I wonder why the following code produces me CS0106 compile-time error:
error CS0106: The modifier 'readonly' is not valid for this item
The code:
class MyClass
{
private readonly int _value
{
get
{
if (_value < 0)
return -1 * _value;
return _value;
}
}
In my understanding I do nothing wrong inside get as I just read the value.
I agree that calculations for readonly's property getter look awkward from the logical point of view.
P.S. Code inside get has no practical sense - it is just a "something that reads the _value"
UPDATE
In short initially I thought that it would be quite logic to make a readonly property by using readonly keyword.
I missed the main thing about readonly property that is available from Microsoft documentation:
The readonly keyword is a modifier that you can use on fields.
No sarcasm...
You get a compile error because it's not part of the grammar for the language.
First, By nature of having only a get, then you're already making the property "readonly".
Second, you need to think of the property as syntactic sugar around two methods
int getValue() and void setValue (int). Would it make sense to set the methods as "readonly"?
Third, setting the property as readonly wouldn't make sense since the property as a construct is not mapped to anything in memory. See the previous point about how it's basically a nice way of writing (up to) two methods.
Implementing only Get for a property is like already readonly. so if you want to achieve implementing the similar behavior, below will be the working code.
class MyClass
{
private readonly int _value = -5; // < some value> or<set it in the constructor>;
private int ReadableValue
{
get
{
return Math.Abs(_value);
}
}
}
Related
In some article I found this:
public interface ICargo {
int FoodStorage { get => 100; }
}
What does the part => 100 mean?
From the context it looks like a default value. But as I know this is not how the default value is set. At least, I've never seen this kind of syntax in this context.
I've tried googling, it didn't help.
The syntax is called expression-bodied property/member.
It can be used for a read-only propery as demonstrated by your code.
get => 100;
Is equivalent to:
get { return 100; }
But in your specific case there is another issue involved:
Since you use it in an interface, it actually provides a default implementation for the property.
If a class implementing the interface does not provide impelmentation for this property, the default provided by the interface (i.e. have the property retuning 100) will be used.
This is called default interface implementation and it is available from C# 8.0 only.
It is expression bodies property, its short form of writing a property which has only getter and has the constant value.
Its equivalent is
public int FoodStorage
{
get { return 100; }
}
and its read-only property, the expression-bodied property is available from C# 6.0
It's an expression bodied element basically it would behave the same as
public interface ICargo
{
int FoodStorage { get { return 100; }
}
Making use of a lambda expression can make the code cleaner without the excess brackets. You can use both syntax wherever you can use properties.
I have this code:
private int _someProperty;
public int SomeProperty
{
get => _someProperty;
set => SetProperty(ref _someProperty, value);
}
private void SetProperty<T>(ref T field, T value)
{
if (!field.Equals(value))
{
field = value;
}
}
I need the SetProperty<T> because I need a set logic in a big class with lots of properties, and that logic applies to all of them.
The code works for the case of _somePropertybeing a variable. But in my case, it does not work because I reference to another property of a nested class, so I get the compilation error: "a property or indexer may not be passed as an out or ref parameter".
As properties are methods under the hood, I tried something like:
private setProperty<T>(ref Action<T> property, T value) {
//meaningful code
}
But I get the compilatuion error anyhow.
Is there a direct way to pass a property by reference to directly solve this problem somehow?
No, basically.
There is a potential loophole around mutable ref-returning get-only properties, but that probably won't help you because:
you can't have any set logic in a mutable ref-returning get-only property
this is an absurdly niche scenario that the majority of devs don't know exists, and will never need to use :)
Often when coding in C# I like to use this pattern for a lazy getter property:
private string _myProp;
string MyProp => _myProp ?? (_myProp = getMyProp());
I think this is pretty standard C# practice. The function getMyProp() is just some function that computes and returns a string. It is called just once to initialize the property, and henceforth it's cached. I can use this for any object type I like, not just string. However, when I try to do it for a primitive type like an int, I run into an issue. For example, if I try the following:
private int _operationCount;
int OperationCount => _operationCount ?? (_operationCount = GetOperationCountFromUser());
I get a compiler error here. It says:
Error CS0019 Operator '??' cannot be applied to operands of type 'int' and 'int'
I understand the error means that int is a primitive type, so we can't apply the null-checking operator to it, because an int is never null. But is there any way I can achieve what I want here? I'm looking for a solution with the following:
On the first access, the int property is initialized to the return value of the function call.
On subsequent accesses, the int property is retrieved from a loaded variable in memory i.e. the function is not called again.
Update: Why Write Properties Like This?
The original question just cited "laziness" as the reason for writing one of these properties, but as I collaborated on this question I realised that probably the primary use case I have for the above pattern using the ?? operator is enforced initialization. By forcing initialization of a property this way, it'll always be initialized the first time you access it. Meaning you don't have to worry about injecting an initial value into multiple constructors- which clutters them up on the one hand and also isn't reliable because you might forget to initialize in one of the constructors.
One solution is to make the backing type nullable, and put a call to the Value property on the RHS:
private int? _operationCount;
public int OperationCount => _operationCount ?? (_operationCount = GetOperationCountFromUser()).Value;
Here's a full working solution with a dummy implementation of the backing function:
using System;
public class Program
{
public static void Main()
{
X x = new X();
Console.WriteLine("Hello World " + x.OperationCount);
}
}
class X
{
private int? _operationCount;
public int OperationCount => _operationCount ?? (_operationCount = GetOperationCountFromUser()).Value;
private int GetOperationCountFromUser() => 38;
}
Thanks to juharr's comment, the explanation for why this works is because the compiler converts nullable ?? expression to nullable.GetValueOrDefault(expresion) when nullable is a Nullable<T>. This explains why the RHS, the default, must be a primitive type, while the LHS is the nullable type.
I personally don't see anything bad in accessing lazy object through Value (at least it shows you explicitly that there can be a delay when you getting the value). But you can skip even this and become very lazy. Unfortunately, you cannot define an implicit operator for conversion between two third party types, but you can inherit from Lazy<T> and define an implicit conversion for your type:
public class VeryLazy<T> : Lazy<T>
{
public VeryLazy(Func<T> valueFactory) : base(valueFactory) { }
public static implicit operator T (VeryLazy<T> lazy) => lazy.Value;
}
And usage becomes very lazy - you can use operationCount whenever you want to use int:
class X
{
private readonly VeryLazy<int> _operationCount = new VeryLazy(GetOperationCountFromUser);
public int OperationCount => _operationCount; // implicit conversion to int
private static int GetOperationCountFromUser() => 38;
}
But I'm not that lazy, and I find code without implicit conversions more readable
class X
{
private readonly Lazy<int> _operationCount = new Lazy(GetOperationCountFromUser);
public int OperationCount => _operationCount.Value; // we see there can be delay
private static int GetOperationCountFromUser() => 38;
}
Also Lazy<T> is better than using nullable types. Sometimes object which initialization you defer might not be available - lazy would return null in that case (e.g. when you tried to get something from the database, but there is no value). What would nullable field tell you in that case? You might end up trying to initialize it on each property access.
I ran into this issue today when creating a struct to hold a bunch of data. Here is an example:
public struct ExampleStruct
{
public int Value { get; private set; }
public ExampleStruct(int value = 1)
: this()
{
Value = value;
}
}
Looks fine and dandy. The problem is when I try to use this constructor without specifying a value and desiring to use the defaulted value of 1 for the parameter:
private static void Main(string[] args)
{
ExampleStruct example1 = new ExampleStruct();
Console.WriteLine(example1.Value);
}
This code outputs 0 and does not output 1. The reason is that all structs have public parameter-less constructors. So, like how I'm calling this() my explicit constructor, in Main, that same thing occurs where new ExampleStruct() is actually calling ExampleStruct() but not calling ExampleStruct(int value = 1). Since it does that, it uses int's default value of 0 as Value.
To make matters worse, my actual code is checking to see that int value = 1 parameter is within a valid range within the constructor. Add this to the ExampleStruct(int value = 1) constructor above:
if(value < 1 || value > 3)
{
throw new ArgumentException("Value is out of range");
}
So, as it stands right now, the default constructor actually created an object that is invalid in the context I need it for. Anyone know how I can either:
A. Call the ExampleStruct(int value = 1) constructor.
B. Modify how the default values are populated for the ExampleStruct() constructor.
C. Some other suggestion/option.
Also, I am aware that I could use a field like this instead of my Value property:
public readonly int Value;
But my philosophy is to use fields privately unless they are const or static.
Lastly, the reason I'm using a struct instead of a class is because this is simply an object to hold non-mutable data, should be fully populated when it is constructed, and when passed as a parameter, should not be able to be null (since it is passed by value as a struct), which is what struct's are designed for.
Actually, MSDN has some good guidance on struct
Consider defining a structure instead of a class if instances of the
type are small and commonly short-lived or are commonly embedded in
other objects.
Do not define a structure unless the type has all of the following
characteristics:
It logically represents a single value, similar to primitive types
(integer, double, and so on).
It has an instance size smaller than 16 bytes.
It is immutable.
It will not have to be boxed frequently.
Notice that they are considerations for considering a struct, and its never a "this should always be a struct". That is because the choice to use a struct can have performance and usage implications (both positive and negative) and should be chosen carefully.
Notice in particular that they don't recommend struct for things > 16 bytes (then the cost of copying becomes more expensive than copying a reference).
Now, for your case, there is really no good way to do this other than to create a factory to generate a struct for you in a default state or to do some sort of trick in your property to fool it into initializing on first use.
Remember, a struct is supposed to work such that new X() == default(X), that is, a newly constructed struct will contain the default values for all fields of that struct. This is pretty evident, since C# will not let you define a parameterless constructor for a struct, though it is curious that they allow all arguments to be defaulted without a warning.
Thus, I'd actually suggest you stick with a class and make it immutable and just check for null on the methods that it gets passed to.
public class ExampleClass
{
// have property expose the "default" if not yet set
public int Value { get; private set; }
// remove default, doesn't work
public ExampleStruct(int value)
{
Value = value;
}
}
However, if you absolutely must have a struct for other reasons - but please consider the costs of struct such as copy-casts, etc - you could do this:
public struct ExampleStruct
{
private int? _value;
// have property expose the "default" if not yet set
public int Value
{
get { return _value ?? 1; }
}
// remove default, doesn't work
public ExampleStruct(int value)
: this()
{
_value = value;
}
}
Notice that by default, the Nullable<int> will be null (that is, HasValue == false), thus if this is true, we didn't set it yet, and can use the null-coalescing operator to return our default of 1 instead. If we did set it in the constructor, it will be non-null and take that value instead...
I don't think it's good design to have a struct ExampleStruct such that
default(ExampleStruct)
i.e. the value where all instance fields are zero/false/null, is not a valid value of the struct. And as you know, when you say
new ExampleStruct()
that's exactly the same as default(ExampleStruct) and gives you the value of your struct where all fields (including "generated" fields from auto-properties) are zero.
Maybe you could do this:
public struct ExampleStruct
{
readonly int valueMinusOne;
public int Value { get { return valueMinusOne + 1; } }
public ExampleStruct(int value)
{
valueMinusOne = value - 1;
}
}
I guess the compiler is actually picking the automatic default ctor for structs here http://msdn.microsoft.com/en-us/library/aa288208(v=vs.71).aspx, rather than using your ctor with the default values.
added references:
http://csharpindepth.com/Articles/General/Overloading.aspx (Optional parameters section)
Although some languages (CIL if nothing else) will allow one to define a struct constructor such that new T() has fields set to something other than their "all zeroes" defaults, C# and vb.net (and probably most other languages) take the view that since things like array elements and class fields must always be initialized to default(T), and since having them be initialized to something which didn't match new T() would be confusing, structures shouldn't define new T() to mean something other than default(T).
I would suggest that rather than trying to jinx a default parameter in a parameterized constructor, you simply define a static struct property which returns your desired default value, and replace every occurrence of new ExampleStruct() with ExampleStruct.NiceDefault;.
2015 Addendum
It appears that C# and VB.NET may ease the prohibition against defining parameterless struct constructors. This may cause a statement like Dim s = New StructType() to assign s a value which is different from the value given to new array items of type StructType. I'm not terribly keen on the change, given that new StructType is often used in places where something analogous to C#'s default(StructType) would be more appropriate if it existed. VB.NET would allow Dim s As StructType = Nothing, but that seems rather hokey.
why do you have public ExampleStruct(int value = 1) : this() ?
shouldn't it be public ExampleStruct(int value = 1)? I think the :this() is creating the no-parameter constructor.
I am self-studying a C# reference and it gives the following information:
1.21.4. Declaring Generic Parameters
Generic parameters can be introduced in the declaration of classes, structs, interfaces, delegates (see the upcoming "Delegates" section), and methods. Other constructs, such as properties, cannot introduce a generic parameter, but can use a generic parameter. For example, the property Value uses T:
public struct Nullable<T>
{
public T Value {get;}
}
First, I get an error trying to compile this saying that it must contain a body because it is neither abstract nor extern or that automatic parameters must have both get and set accessors.
Second, assuming it is wrong and I correct it by adding "set;", I cannot seem to format a call to it successfully.
That is just showing the API of Nullable<T> rather than the implementation. It's not meant to be compiled - System.Nullable<T> is part of the framework, you don't have to implement it yourself.
You appear to be reading "C# 3.0 in a Nutshell". Well, the example is just that - an example. It is only intended to illustrate how the Value property of the Generic Nullable class exposes the generic parameter declared by the containing type.
It isn't meant to be part of a compilable example.
I'm not sure if you just picked a bad example for your struct name (since Nullable is a framework struct), but if not, the error is due to the fact that you have no set accessor in your property. Automatic properties (added in C# 3.0) need both a get and set property. So, if you change the code to:
public struct Nullable<T>
{
public T Value {get; set; }
}
it should work. In this case, the error had nothing to do with generics. To create an instance, you could use:
Nullable<int> i = new Nullable<int>();
This will make it compile. However, as both Jon and Cerebrus has pointed out, it's probably just an example to show the workings of generics.
For an automatic property you always need both a getter and setter. Without a getter you could set the value, but nothing could ever retrieve it. Without a setter the value would always be the default because nothing could ever set it:
//tradition
private T _value;
public T Value
{
get
{
return _value;
}
}
//locally, _value can always be set
//Auto-matically implemented property
public T Value { get; }
//there is never a way to set it
//with this it can be privately set, but is get only to everyone else
public T Value{ get; private set; }
Your question here seems to be about auto-properties, rather than generics.
Auto-properties must have a set accessor, although it doesn't have to have the same visibility as the get:
public T Value { get; private set; }
You can call the set in the constructor:
public Nullable ( T value ) {
Value = value;
}
Although in this case you're dealing with a struct, and they always have a default (parameterless) constructor - you have to be a bit more careful with structs and auto-properties.
In .net there's already a nullable generic:
Nullable<int> i = GetCounterThatMightBeNull();
int j = 0;
if( i.HasValue )
j = i.Value;
...
This was added in .Net 2 (at the same time as generics), and while early betas looked like the code above they streamlined it the final version:
//int? is shorthand for Nullable<int>
int? i = GetCounterThatMightBeNull();
// ?? is shorthand for the null check
int j = i ?? 0;
//or
if( i == null ) {
//this works even though Nullable<int> is a struct
}