Quite often I come across the need for small immutable data structures. Others would probably use Tuples in these cases, but I really dislike that Tuples don't read nicely and don't express that much meaning. A Value2 of int doesn't tell me anything.
An example would be creating a lookup table (Dictionary) for a combination of two properties, i.e. Name and Rating.
The shortest way to make an immutable struct for these cases that I know of is this:
public struct Key
{
public string Name { get; private set; }
public int Rating { get; private set; }
public LolCat(string name, int rating) : this()
{
Name = name;
Rating = rating;
}
}
// useage
var key = new Key( "MonorailCat", 5 );
In my opinion there is still a lot of 'syntactic fat' in here that I would like to get rid of.
I could make it a lot more readable when I would just expose fields directly.
public struct Key
{
public string Name;
public int Rating;
}
// useage
var key = new Key { Name = "MonorailCat", Rating = 5 };
I really like the syntax of this, because there is barely any syntactic fat. The big disadvantage is of course that it is not immutable, with all it's dangers.
In the ideal case I would just like to have a special type for this, with the real bare minimum of definition, like:
public immutable struct Key
{
string Name;
int Rating;
}
// useage (needs compiler magic)
var key = new Key( Name: "MonorailCat", Rating: 5 );
Question
Is there a real world solution something closer to the example on the bottom, to reduce the amount of syntactic fat for a very simple immutable struct?
As of C# 6, you can write fairly compact struct initializers:
public struct Key
{
public string Name { get; }
public int Rating { get; }
public Key(string name, int rating)
{
this.Name = name;
this.Rating = rating;
}
}
... which is at least significantly shorter. I'd strongly advise implementing IEquatable<Key>, mind you.
Note that as you're dealing with a struct, you'll still be able to write:
Key key = new Key();
Console.WriteLine(key.Rating); // 0
... which may not be a problem, but generally needs considering at least.
Before C# 6, I'd actually go even longer than your current code, in order to write the properties as read-only properties:
public struct Key
{
private readonly string name;
private readonly int rating;
public string Name { get { return name; } }
public int Rating { get { return rating; } }
public Key(string name, int rating)
{
this.name = name;
this.rating = rating;
}
}
I feel this makes it more clearly "meant to be immutable" - if you've got a writable property, even if the setter is only private, that doesn't convey the right impression IMO. (Although it's worth noting that immutability in structs is always a little bit of a pretense, given that you can assign to this in members...)
AFAIK, the shortest you can write is using readonly, which is hardly shorter than your struct using properties:
public struct Key
{
public readonly string Name;
public readonly int Rating;
public Key(string name, int rating){
Name = name;
Rating = rating;
}
}
var key = new Key("MonorailCat", 5);
In C# 7.2 there is a readonly struct.
readonly public struct ReadonlyPoint3D
{
public ReadonlyPoint3D(double x, double y, double z)
{
this.X = x;
this.Y = y;
this.Z = z;
}
//setters would not compile
public double X { get; }
public double Y { get; }
public double Z { get; }
private static ReadonlyPoint3D origin = new ReadonlyPoint3D();
public static ref readonly ReadonlyPoint3D Origin => ref origin;
public ReadonlyPoint3D Scale(double factor)
{
/* all fail compilation
X *= factor;
Y *= factor;
Z *= factor;
*/
return new ReadonlyPoint3D(X * factor, Y * factor, Z * factor);
}
}
The compiler enforces that all members are readonly.
This passed as 'in' reference rather than copy of receiver which is usually more efficient.
Reference
Related
My English skill is poor because I'm not a native English speaker.
please understand.
I will tell you about what I want detailly.
I created a class below
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public class TestClassForNetwork
{
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 11), JsonIgnore]
public byte[] field1;
public short field2;
public short field3;
public short field4;
}
As you know, when deserializing or serializing, I pay attention to converting to a specified endian. so I added the below code.
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public class TestClassForNetwork
{
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 11), JsonIgnore]
public byte[] field1;
public short field2;
public short field3;
public short field4;
public void ToHostOrder()
{
if (!BitConverter.IsLittleEndian) return;
field2 = IPAddress.NetworkToHostOrder(field2);
field3 = IPAddress.NetworkToHostOrder(field3);
field4 = IPAddress.NetworkToHostOrder(field4);
}
public void ToNetworkOrder()
{
if (!BitConverter.IsLittleEndian) return;
field2 = IPAddress.HostToNetworkOrder(field2);
field3 = IPAddress.HostToNetworkOrder(field3);
field4 = IPAddress.HostToNetworkOrder(field4);
}
}
Here, I thought if it is added the field that has more 2byte, I have to modify ToHostOrder and ToNetworkOrder functions. and this will increase the cost of maintenance.
So I thought the idea was as below.
public void ToHostOrder()
{
if (!BitConverter.IsLittleEndian) return;
// filtering only short type in this class.
FieldInfo[] shortFields;
foreach(var shortField in shortFields)
shortField = IPAddress.NetworkToHostOrder(shortField);
// filtering only int type in this class.
FieldInfo[] intFields;
foreach(var intField in intFields)
intField = IPAddress.NetworkToHostOrder(intField);
}
public void ToNetworkOrder()
{
if (!BitConverter.IsLittleEndian) return;
// filtering only short type in this class.
FieldInfo[] shortFields;
foreach(var shortField in shortFields)
shortField = IPAddress.HostToNetworkOrder(shortField);
// filtering only int type in this class.
FieldInfo[] intFields;
foreach(var intField in intFields)
intField = IPAddress.HostToNetworkOrder(intField);
}
This idea seems to be poor if the count of fields in class is small because the readability is poor but I think this idea will decrease the cost of maintenance if the count of field is bigger because it is no need to worry to convert to a specified endian.
Could someone tell me how to realize this idea?
Thank you for reading.
You can solve this using System.Reflection and getting all fields of a short type, and then using GetValue and SetValue to get and set the respective fields
In the constructor I set a List of all the fields, so it's only used once. Using System.Linq's Where makes sure we only get fields of short type
public TestClassForNetwork()
{
shortFields = this.GetType().GetFields().Where(field => field.FieldType == typeof(short)).ToList();
}
public List<FieldInfo> shortFields = new List<FieldInfo>();
Taking the same sample fields you have
public byte[] field1;
public short field2;
public short field3;
public short field4;
You can implement ToHostOrder and ToNetworkOrder like this
public void ToHostOrder()
{
if (!BitConverter.IsLittleEndian) return;
foreach (var shortField in shortFields)
{
shortField.SetValue(this, IPAddress.NetworkToHostOrder((short)shortField.GetValue(this)));
}
}
public void ToNetworkOrder()
{
if (!BitConverter.IsLittleEndian) return;
foreach (var shortField in shortFields)
{
shortField.SetValue(this, IPAddress.NetworkToHostOrder((short)shortField.GetValue(this)));
}
}
Going forward, you should only need to add new short fields in your class, for it to be implemented in the methods
you can use MemoryPack library and it can do it for you amazingly with higher performance and code readability.
It doesn't use reflection and all of the stuff is being generated in compile time.
It handles endian and other OS/CPU architecture stuff
It is being maintained by a strong open-source community
It's performance is 50X better than Json or ProtoBuff serialization
Imagine a class which can, in principle, be created by specifying the value of one of two properties, both of which happen to have the same type. The following code accomplishes this by using a combination of named and optional parameters to discriminate between the two constructors:
class Program
{
static void Main()
{
//Note: these 2 ctors are distinguished only by the argument naming convention:
thing thingWithMass = new thing(mass: 10);
thing thingWithVolume = new thing(vol: 25);
}
class thing
{
int Density = 3;
int Mass;
int Vol;
public thing(int mass)
{
Mass = mass;
Vol = Mass/Density;
}
// Note the use of the optional variable to distinguish this ctor:
public thing(int vol, bool isVol=true)
{
Vol = vol;
Mass = Vol * Density;
}
}
}
So (somewhat surprisingly) this code compiles and works perfectly, but is it bad form? It seems a bit like trickery, and I'm wondering if there is a lurking danger that isn't readily apparent to me? Does it smell?
NOTE: In this particular case, I realize that I could accomplish essentially the same thing with a single constructor that looks like this:
public thing(int mass=0, int vol=0) //plus a couple of if() statements in the body
but in my real situation there are quite a few other parameters involved, and combining them all into one constructor gets a bit unwieldy and hard to read.
If your class has many constructors with very different logic and conflicting types of arguments, consider using static factory methods:
public static Thing CreateFromMass(int mass)
{
return new Thing(mass, 0);
}
public static Thing CreateFromVol(int vol)
{
return new Thing(0, vol);
}
You can make your constructor non-public if you use factory methods like this.
Distinguishing constructors based on parameter names, while possible, is not recommended, because it is very uncommon in C#. Note that you are also forced to use tricks with optional parameters to achive this — a clear indicator that you are doing something wrong.
IMO it's a bit of a smell. What if a consumer calls thing(10, false). That has the unintended consequence of creating thing with the wrong value.
I can think of two possible solutions
1) Use a factory as described by Athari.
2) Create types for Mass and Volume. For example,
class Mass
{
private readonly int _mass;
public Mass(int mass) { _mass = mass; }
public int Value { get { return _mass; } }
}
class Volume
{
private readonly int _volume;
public Mass(int volume) { _volume = volume; }
public int Value { get { return _volume; } }
}
You can then change your signatures to
thing(Volume volume)
thing(Mass mass)
In response to your comment about simple arithmetic operations not working with the second approach, you can define implicit conversions to and from int for Mass and Volume.
abstract class Number
{
public static implicit operator int(Number number)
{
return number.Value;
}
public abstract int Value { get; set; }
}
internal class Mass : Number
{
public override int Value { get; set; }
public static implicit operator Mass(int val) { return new Mass(){ Value = val }; }
}
internal class Volume : Number
{
public static implicit operator Volume(int val) { return new Volume(){ Value = val }; }
public override int Value { get; set; }
}
var mass = new Mass { Value = 10 };
var volume = new Volume { Value = 20 };
int product = mass * volume; // should work
mass = 10 * 20; // should also work
I have some C++ code that implements a basic Pixel class. Here's just a stub of the important bits I have:
// Pixel.h
template <class SizeType>
struct Pixel
{
public:
typedef SizeType Size;
Size R;
Size G;
Size B;
static Size Min;
static Size Max;
TPixel(Size R = Min, Size G = Min, Size B = Min);
};
#include "Pixel.impl"
// Pixel.impl
template <class SizeType> SizeType Pixel<SizeType>::Min = std::numeric_limits<Size>::min();
template <class SizeType> SizeType Pixel<SizeType>::Max = std::numeric_limits<Size>::max();
template <> float Pixel<float>::Min = 0;
template <> float Pixel<float>::Max = 1;
template <> double Pixel<double>::Min = 0;
template <> double Pixel<double>::Max = 1;
And in C# I'm trying to duplicate this:
struct Pixel<Size> where Size : struct
{
public Size R;
public Size G;
public Size B;
public static const Size Min; // What should I do here?
public static const Size Max;
}
Except I have no idea how I can include this Min / Max size into the type. I'd like to be able to have a uniform Pixel interface which allows you do things like clamping, adding, scaling, etc.
I'm running into a similar solution when I'm trying to deal with Vectors and Matrices of potentially arbitrary type. Can anyone advise me on how I can accomplish what the above C++ code is doing?
Unlike C++ template specialization, there is no such thing as specialization of a generic in .Net.
You can't initialize a T instance to anything but a T, unless you have a constraint, so you can't use a static constructor to try to work around the problem.
As far as I know, there is no constraint that allows you to specify only types that either are numeric types, or have conversions from numeric types.
I suggest you just make two different types of classes:
public struct PixelFloat
{
public float R { get; set; }
public float G { get; set; }
public float B { get; set; }
public const float Min = 0.0f;
public const float Max = 1.0f;
}
public struct PixelDouble
{
public double R { get; set; }
public double G { get; set; }
public double B { get; set; }
public const double Min = 0.0f;
public const double Max = 1.0f;
}
This is effectively the same thing anyhow, as this is what it would compile to under the covers. Other solutions won't buy you much compared to this, as you'll still have to type in the type: Pixel<double> Pixel<float>.
Also, in cases like this, I would suggest you use names that show that you're using types from your generic parameters. Size isn't obviously a generic parameter. TSize is. And TSize doesn't describe what the type does, it just describes how it varies. Instead you should name it something like TValue.
The only way to do this sort of thing would be to add an interface constraint to Size which requires Size to have Max and Min methods or something like that. Of course, the definitions would no longer be necessary in that case.
Assuming that what you are trying to accomplish is to do template specialization in C# generics, this is not possible.
Here is an MSDN link comparing the differences between the two but the highlights are:
C# does not support explicit specialization; that is, a custom implementation of a template for a specific type.
C# does not support partial specialization: a custom implementation for a subset of the type arguments.
You would have to do something like this:
static class Pixel
{
public static Size Min<Size>() where Size : struct;
public static Size Max<Size>() where Size : struct;
}
struct Pixel<Size> where Size : struct
{
public Size R;
public Size G;
public Size B;
}
And then call it like so:
Pixel<double> doublePixel;
var max = Pixel.Max<double>();
Does that work for you?
Something like this, maybe?
public struct Pixel<Size> where Size : struct
{
private enum DEF_TYPES
{
MIN,
MAX
}
private static Dictionary<Type, Dictionary<DEF_TYPES, object>> m_Defs = new Dictionary<Type, Dictionary<DEF_TYPES, object>>
{
{
typeof(float),
new Dictionary<DEF_TYPES, object> {
{DEF_TYPES.MIN, 0f},
{DEF_TYPES.MAX, 1f}
}
},
{
typeof(double),
new Dictionary<DEF_TYPES, object> {
{DEF_TYPES.MIN, 0d},
{DEF_TYPES.MAX, 1d}
}
}
};
private static Size GetValue(DEF_TYPES def_type)
{
if(!m_Defs.ContainsKey(typeof(Size)))
throw new ArgumentException("No default values for template " + typeof(Size));
if(!m_Defs[typeof(Size)].ContainsKey(def_type))
throw new ArgumentException("No default value '" + def_type + "' for template " + typeof(Size));
return (Size)m_Defs[typeof(Size)][def_type];
}
public Size R;
public Size G;
public Size B;
public static readonly Size Min = GetValue(DEF_TYPES.MIN);
public static readonly Size Max = GetValue(DEF_TYPES.MAX);
}
And used as:
Console.WriteLine(Pixel<float>.Max);
Console.WriteLine(Pixel<float>.Min);
Console.WriteLine(Pixel<double>.Max);
Console.WriteLine(Pixel<double>.Min);
And;
Pixel<double>.Min = 4;
Won't compile, as expected.
Not ideal, but it works.
Well I am learning properties and I am not sure about the following:
class X
{
private int y;
public X(int number)
{
this.Y=number; // assign to property
OR
this.y=number //?
}
public int Y;
{
get; set;
}
}
When you use auto-properties (get; set; or a variant thereof), the backing variable is not accessible. Those can, for the most part, be treated as simple variables, especially internally.
If you need to perform custom validation or mutation logic in the mutator, or otherwise have the need for an explicit backing variable, you cannot use auto-properties but have to write stub get and set methods yourself.
They do different things; I would do Y = number; and remove the (unused) field y. In an automatically implemented property, the compiler creates it's own field (with a horrible name that you can't see in C#) - you don't need to provide your own field. So:
class X
{
public X(int y)
{
Y = y;
}
public int Y { get; set; }
}
Other points: changed number to y to be clearer to the caller, and also you don't need this. since it isn't ambiguous (field vs parameter, etc).
Only assign to a field (private int y) inside the property representing that field (public int Y {get;set}). No where else in the class should the backing field be assigned to directly. Always do it through the property... yes even in the constructor. It follows from the do not repeat yourself (DRY) principle.
This is recommended because whenever in future you want to associate some behavior to be triggered by that assignment you only have a single place (the set accessor) to write code into.... not all the places where the field is assigned to !!
class X
{
private int y; //not strictly necessary but good for documentation
public X(int number)
{
Y = number;
}
public int Y { get; set; }
}
When you use autoproperties like:
public int Y;
{
get; set;
}
You don"t need a private property because it's autogenerated. so you class will be:
class X
{
public X(int number)
{
Y = number;
}
public int Y // no semicolon here, comment added for edit length
{
get; set;
}
}
Hope this helps
You have two choices :
class X
{
private int y;
public int Y
{
get { return y; }
set { y = value; }
}
public X(int number)
{
Y = number;
//equivalent to
y = number;
// but you should use the public property setter instead of the private field
}
}
or with auto-properties , it's even simpler :
class X
{
private int y;
public int Y
{
get; set;
}
public X(int number)
{
Y = number;
}
}
When not using auto-properties I always use the Property setter because there can or will be code in the setter that I need to be executed. This code could be a domain check or the raising of an event such as PropertyChanged.
A point I usually try to make about accessing backing variables:
Sometimes the public getter might contain complicated data validation,raising property changed events or some other complex code that is triggered when some external code changes it's value.
When changing that value internally (from inside the class), it might be a valid point to use the backing variable directly if your intention is to skip all the validation and events from the public setter. It's like saying "i'm the class instance, I know what I'm doing". This way the public setter is acting like a guard-dog, sanitizing external input, while I can still set the property internally to whatever I need.
class X
{
private int y; //not strictly necessary but good for documentation
public X(int number)
{
y = GetYValueFromDB(); //we assume the value from DB is already valid
}
public int Y {
get{ return y};
set {
if (ComplexValidation(value)
{
RaiseOnYPropertyChanged();
y = value;
}
}
}
PHP has a language construct list() which provides multiple variables assignment in one statement.
$a = 0;
$b = 0;
list($a, $b) = array(2, 3);
// Now $a is equal to 2 and $b is equal to 3.
Is there a similar thing in C#?
If not, is there any workaround which may help to avoid code like the following, without having to deal with reflection?
public class Vehicle
{
private string modelName;
private int maximumSpeed;
private int weight;
private bool isDiesel;
// ... Dozens of other fields.
public Vehicle()
{
}
public Vehicle(
string modelName,
int maximumSpeed,
int weight,
bool isDiesel
// ... Dozens of other arguments, one argument per field.
)
{
// Follows the part of the code I want to make shorter.
this.modelName = modelName;
this.maximumSpeed = maximumSpeed;
this.weight= weight;
this.isDiesel= isDiesel;
/// etc.
}
}
No, I'm afraid there isn't any good way to do that, and code like your example gets written often. It sucks. My condolences.
If you're willing to sacrifice encapsulation for concision, you can use object initializer syntax instead of a constructor for this case:
public class Vehicle
{
public string modelName;
public int maximumSpeed;
public int weight;
public bool isDiesel;
// ... Dozens of other fields.
}
var v = new Vehicle {
modelName = "foo",
maximumSpeed = 5,
// ...
};
I think you're looking for object and collection initializers.
var person = new Person()
{
Firstname = "Kris",
Lastname = "van der Mast"
}
for example where Firstname and Lastname are both properties of the class Person.
public class Person
{
public string Firstname {get;set;}
public string Lastname {get;set;}
}
"Multiple variable initialization" or "Multiple variable assignment" ?
For initialization
$a = 0;
$b = 0;
list($a, $b) = array(2, 3);
would be:
int a=2, b=3;
For assignment, there's no shortcut. It has to be two statement, but if you like, you can put the two statements on one line:
a=2; b=3;
Yes - you can eliminate all the code in the constructor with object initializers (new for C# 3.0). Here is a pretty good explanation:
http://weblogs.asp.net/dwahlin/archive/2007/09/09/c-3-0-features-object-initializers.aspx