What does the part "=> 100" mean in the C# property? - c#

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.

Related

CS0106 compile error: readonly property and getter

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);
}
}
}

Are parentheses mandatory to include in C# methods?

I have seen multiple tutorials that show C# method creation with parentheses containing parameters or simple empty. I have also seen a C# method written with out parentheses.
public int Value {
get{ return _Value; }
set{ _Value = value; }
}
I haven't tested out that code but is this allowed? Is it considered bad form?
That is a Property and not a method. If you create a Method then it requires ().
As in Philip's answer, your example code is actually a Property,
But you perhaps have hit on something that many actually miss and that is that Properties are implemented using one or two methods. They get created for you by the compiler and contain the contents of each of the get and/or set blocks.
So, a property of:
public string Name {
get {
return "Fred";
}
}
Is a nicer way of writing:
public string GetName() {
return "Fred";
}
Parentheses are mandatory when declaring or invoking a method.
As others have said, what you've shown there is a property, which is implemented as one or two methods behind the scenes (one for each of the "getter" and "setter").
However, you will sometimes see method names without parentheses - these are called method groups and are used to construct instances of delegate types.
For example:
public void Foo(string x)
{
...
}
...
Action<string> action = Foo;
Here Action<string> is a delegate type representing a call with a single string parameter and a void return type. This assignment creates an instance of that delegate type which will call the Foo method when it's invoked, e.g.
action("Test");
will call Foo with an argument of "Test".
That is a property, not a method. A method requires parenthesis.
Bad form depends on context, there are a few design considerations to take into account when deciding to use a property or not.
MSDN has a nice list here: http://msdn.microsoft.com/en-us/library/ms229006.aspx

C# Generics : how to use x.MaxValue / x.MinValue (int, float, double) in a generic class

I'm using the WPF Extended Toolkit ( http://wpftoolkit.codeplex.com/ ).
It has a nice NumericUpDown control that I'd like to use, but internally it uses doubles - which means it uses double.MinValue and double.MaxValue.
I'd like to use the same control, but I need a generic version - for ints it needs to use int.MaxValue/MinValue, for floats float.MaxValue/MinValue, etc. (I think you get the idea :))
So I though about copying the NumericUpDown to a GNumericUpDown, where T would ofcourse be the Type..
But this doesn't work, because a generic Type doesn't have MinValue / MaxValue.
And normally I'd use the 'where' clause to specify a base-type, but this doesn't work as afaik there's no common interface that defines 'MinValue' and 'MaxValue'.
Is there a way to solve this with generics, or do I really need to copy/paste/search&replace the original NumericUpDown for each type ?
Well, given that you can get at the type at execution time, you could rely on the fact that all of the numeric types in .NET have MinValue and MaxValue fields, and read them with reflection. It wouldn't be terribly nice, but easy enough to do:
using System;
using System.Reflection;
// Use constraints which at least make it *slightly* hard to use
// with the wrong types...
public class NumericUpDown<T> where T : struct,
IComparable<T>, IEquatable<T>, IConvertible
{
public static readonly T MaxValue = ReadStaticField("MaxValue");
public static readonly T MinValue = ReadStaticField("MinValue");
private static T ReadStaticField(string name)
{
FieldInfo field = typeof(T).GetField(name,
BindingFlags.Public | BindingFlags.Static);
if (field == null)
{
// There's no TypeArgumentException, unfortunately. You might want
// to create one :)
throw new InvalidOperationException
("Invalid type argument for NumericUpDown<T>: " +
typeof(T).Name);
}
return (T) field.GetValue(null);
}
}
class Test
{
static void Main()
{
Console.WriteLine(NumericUpDown<int>.MaxValue);
Console.WriteLine(NumericUpDown<float>.MinValue);
}
}
Note that if you use this with an inappropriate type, I've tried to force a compile-time error as best I can... but it won't be foolproof. If you manage to find a structure with all the right interfaces but without MinValue and MaxValue fields, then any attempt to use the NumericUpDown with that type will cause an exception to be thrown.
The OP made this comment on another answer:
I want to use these controls in my
XAML. My idea was to create a generic
version, and then create empty classes
like NumericUpDownInt :
GNumericUpDown { } Would that be
the way to go, or is there a
better/cleaner way to your knowledge
If you're going to go that route, then just pass the min and max directly:
class abstract GenericNumericUpDown<T>
{
public GenericNumericUpDown(T min, T max) { ... }
}
class NumericUpDownInt : GenericNumericUpDown<int>
{
public NumericUpDownInt() : base(int.MinValue, int.MaxValue) { ... }
}
class NumericUpDownFloat : GenericNumericUpDown<float>
{
public NumericUpDownFloat() : base(float.MinValue, float.MaxValue) { ... }
}
class NumericUpDownDouble : GenericNumericUpDown<double>
{
public NumericUpDownDouble() : base(double.MinValue, double.MaxValue) { ... }
}
You should get the latest source code for the Extended WPF Toolkit. The updated NumericUpDown control allows you to specify what data type to use in the editor. The following code specifies to use an Int32 as the data type instead of the default double. As you can see this is done by setting the ValueType property on the NumericUpDown control.
<extToolkit:NumericUpDown Grid.Row="1" Value="{Binding Age}" Increment="1" Minimum="18" Maximum="65" ValueType="{x:Type sys:Int32}" />
As this is also useful in Testing scenarios:
You may use extension methods, such that in C#6 (introducing nameof) you could write:
public static class TypeExtension
{
public static T MinValue<T>(this Type self)
{
return (T)self.GetField(nameof(MinValue)).GetRawConstantValue();
}
public static T MaxValue<T>(this Type self)
{
return (T)self.GetField(nameof(MaxValue)).GetRawConstantValue();
}
}
and invoke through some admittedly ugly syntax:
var intMinValue = typeof(int).MinValue<int>();
which in your generic method would be
var typeMinValue = typeof(T).MinValue<T>();
Note, that I am not certain that all primitive types declare their Min/Max values as constants. Use GetValue instead.

Need help understanding C# generics

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
}

Why does C# forbid generic attribute types?

This causes a compile-time exception:
public sealed class ValidatesAttribute<T> : Attribute
{
}
[Validates<string>]
public static class StringValidation
{
}
I realize C# does not support generic attributes. However, after much Googling, I can't seem to find the reason.
Does anyone know why generic types cannot derive from Attribute? Any theories?
Well, I can't answer why it's not available, but I can confirm that it's not a CLI issue. The CLI spec doesn't mention it (as far as I can see) and if you use IL directly you can create a generic attribute. The part of the C# 3 spec that bans it - section 10.1.4 "Class base specification" doesn't give any justification.
The annotated ECMA C# 2 spec doesn't give any helpful information either, although it does provide an example of what's not allowed.
My copy of the annotated C# 3 spec should arrive tomorrow... I'll see if that gives any more information. Anyway, it's definitely a language decision rather than a runtime one.
EDIT: Answer from Eric Lippert (paraphrased): no particular reason, except to avoid complexity in both the language and compiler for a use case which doesn't add much value.
An attribute decorates a class at compile-time, but a generic class does not receive its final type information until runtime. Since the attribute can affect compilation, it has to be "complete" at compile time.
See this MSDN article for more information.
I don't know why it's not allowed, but this is one possible workaround
[AttributeUsage(AttributeTargets.Class)]
public class ClassDescriptionAttribute : Attribute
{
public ClassDescriptionAttribute(Type KeyDataType)
{
_KeyDataType = KeyDataType;
}
public Type KeyDataType
{
get { return _KeyDataType; }
}
private Type _KeyDataType;
}
[ClassDescriptionAttribute(typeof(string))]
class Program
{
....
}
This is not truly generic and you still have to write specific attribute class per type, but you may be able to use a generic base interface to code a little defensively, write lesser code than otherwise required, get benefits of polymorphism etc.
//an interface which means it can't have its own implementation.
//You might need to use extension methods on this interface for that.
public interface ValidatesAttribute<T>
{
T Value { get; } //or whatever that is
bool IsValid { get; } //etc
}
public class ValidatesStringAttribute : Attribute, ValidatesAttribute<string>
{
//...
}
public class ValidatesIntAttribute : Attribute, ValidatesAttribute<int>
{
//...
}
[ValidatesString]
public static class StringValidation
{
}
[ValidatesInt]
public static class IntValidation
{
}
Generic Attributes are available since C# 11. Now, this is possible:
[GenericAttribute<int>()]
public int Method();
However, this is not possible yet:
[GenericAttribute<T>()]
public int Method<T>(T param);
T is not known at compile time.
Also,
The type arguments must satisfy the same restrictions as the typeof
operator. Types that require metadata annotations aren't allowed. For
example, the following types aren't allowed as the type parameter:
dynamic
string? (or any nullable reference type)
(int X, int Y) (or any other tuple types using C# tuple syntax).
These types aren't directly represented in metadata. They include annotations that
describe the type. In all cases, you can use the underlying type
instead:
object for dynamic.
string instead of string?.
ValueTuple<int, int> instead of (int X, int Y).
Source: https://learn.microsoft.com/en-us/dotnet/csharp/whats-new/csharp-11#generic-attributes
This is a very good question. In my experience with attributes, I think the constraint is in place because when reflecting on an attribute it would create a condition in which you would have to check for all possible type permutations: typeof(Validates<string>), typeof(Validates<SomeCustomType>), etc...
In my opinion, if a custom validation is required depending on the type, an attribute may not be the best approach.
Perhaps a validation class that takes in a SomeCustomValidationDelegate or an ISomeCustomValidator as a parameter would be a better approach.
This is not currently a C# language feature, however there is much discussion on the official C# language repo.
From some meeting notes:
Even though this would work in principle, there are bugs in most
versions of the runtime so that it wouldn't work correctly (it was
never exercised).
We need a mechanism to understand which target runtime it works on. We
need that for many things, and are currently looking at that. Until
then, we can't take it.
Candidate for a major C# version, if we can make a sufficient number
of runtime versions deal with it.
Generic attributes are supported since .NET 7 and C# 11 (in preview in .NET 6 and C# 10).
My workaround is something like this:
public class DistinctType1IdValidation : ValidationAttribute
{
private readonly DistinctValidator<Type1> validator;
public DistinctIdValidation()
{
validator = new DistinctValidator<Type1>(x=>x.Id);
}
public override bool IsValid(object value)
{
return validator.IsValid(value);
}
}
public class DistinctType2NameValidation : ValidationAttribute
{
private readonly DistinctValidator<Type2> validator;
public DistinctType2NameValidation()
{
validator = new DistinctValidator<Type2>(x=>x.Name);
}
public override bool IsValid(object value)
{
return validator.IsValid(value);
}
}
...
[DataMember, DistinctType1IdValidation ]
public Type1[] Items { get; set; }
[DataMember, DistinctType2NameValidation ]
public Type2[] Items { get; set; }

Categories