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.
Related
I would like to design something that gets the distance between two things. However, these things can be manifest in many obnoxious forms.
Let's say we have a set of classes. (Not necessarily base and derived)
Cat, CoolCat, ReallyCoolCat
All of them have a way to access a position. I would like to write a function call 'DistanceBetween' that gets the distances between the cats.
I can make overloads:
public static float DistanceBetween(Cat cat1, Cat cat2)
{
return Mathf.Abs(cat1.position - cat2.position);
}
public static float DistanceBetween(CoolCat cat1, CoolCat cat2)
{
return Mathf.Abs(cat1.transform.position, cat2.transform.position);
}
// ... etc...
However, then I would have cases where I need to know the distance between a Cat and a CoolCat or the distance between a CoolCat and a ReallyCoolCat. That means...
public static float DistanceBetween(Cat cat1, CoolCat cat2)
{
return Mathf.Abs(cat1.position, cat2.transform.position);
}
public static float DistanceBetween(CoolCat cat1, ReallyCoolCat cat2)
{
return Math.Abs(cat1.tranform.position, cat2.kittyVariables.position);
}
// ... etc ...
But then it just seems arbitrary cause I can rearrange the order of my arguments and my function wouldn't work. So I have to make...
public static float DistanceBetween(CoolCat cat1, Cat cat2)
{
return Mathf.Abs(cat1.tranform.position, cat1.position);
}
public static float DistanceBetween(ReallyCoolCat cat1, CoolCat cat2)
{
return Math.Abs(cat1.kittyVariables.position, cat2.transform.position);
}
// ... etc ...
So This means the amount of code per cute kitties I make grows by n^2. This amount of code growth is not acceptable due to how many cute kitties I want to make. I cannot implement inheritance because my cute kitties (though similar in name) have very different features and are unique. (I could add doggies and the such too.) So what I am thinking is to create an interface 'IDistanceable' that says the implementing class has a 'Position' property and implementing it in each kitty. But this starts to seem like overkill though, all I wanted was something that can rearrange my arguments and make Func(a,b) equal to Func(b,a)...
I don't really know what to do... both solutions (write 500 functions or make interface and lots of junk) both seem wrong.
The interface will NOT work due to the inability to modify some of the cute kitty classes...
Please help me and my cute kitties! Thanks!
If you can't modify the classes, you're best off wrapping them in something you can modify. That way, you can centralize the class-specific logic in one place (the different constructors).
class CatWrapper
{
private int position { get; set; }
public CatWrapper(Cat cat) { ... }
public CatWrapper(CoolCat cat) { ... }
public CatWrapper(ReallyCoolCat cat) { ... }
public DistanceFrom(CatWrapper other) { ... }
}
This is a purely academic answer, since #Andrews Pilser's is far superior for almost any real-world project, but this will solve it for any class that has any conceivable way of representing a location. It makes heavy use of lambda-expressions, and generics, and requires no control over the underlying classes.
The code was written in LINQPad, so it may look a little odd, but it is standard C# (version 7) that can be snapped right in to Visual Studio. File available here.
This uses a Dictionary to store a ToPointConverter for any Type that can be converted to a Point. A ToPointConverter is created from a static method Create that accepts a lambda that returns a Point from the specific generic T.
As you can see, I provide 3 example "kitty" classes that each store their location in completely different ways. The main function creates a converter for each, storing it in the dictionary of converters, and then calculates the distance between the different combination of "kitties". (I may have gotten my distance function wrong, it's late, but that is a minor detail.)
It produces this output:
2.23606797749979
9.05538513813742
2.23606797749979
8.06225774829855
9.05538513813742
8.06225774829855
void Main()
{
//Define conversion functions for anything that can be converted.
converters.Add(typeof(KittyA), ToPointConverter<KittyA>.Create(kitty => kitty.Location));
converters.Add(typeof(KittyB), ToPointConverter<KittyB>.Create(kitty => new Point { X = kitty.X, Y = kitty.Y }));
converters.Add(typeof(KittyC), ToPointConverter<KittyC>.Create(kitty => kitty.MyLocation));
//Declare some kitties
var kitty1 = new KittyA { Location = new Point { X = 1, Y = 1 } };
var kitty2 = new KittyB { X = 3, Y = 2 };
var kitty3 = new KittyC { MyLocation = new Point { X = 2, Y = 10 } };
//Calculate the distances
GetDistance(kitty1, kitty2).Dump();
GetDistance(kitty1, kitty3).Dump();
GetDistance(kitty2, kitty1).Dump();
GetDistance(kitty2, kitty3).Dump();
GetDistance(kitty3, kitty1).Dump();
GetDistance(kitty3, kitty2).Dump();
}
private Dictionary<Type, IToPointConverter> converters = new Dictionary<Type, IToPointConverter>();
//A helper function that does the converts the passed objects in to Points, and calculates the distance between them.
private double GetDistance(object obj1, object obj2)
{
var point1 = GetConvrterFor(obj1).Convert(obj1);
var point2 = GetConvrterFor(obj2).Convert(obj2);
return Math.Sqrt(Math.Pow(point2.X - point1.X, 2) + Math.Pow(point2.Y - point1.Y, 2));
}
//Another helper that gets the IToPointConverter for the object instance passed in.
private IToPointConverter GetConvrterFor(object obj) => converters[obj.GetType()];
//This generic class stores a lambda expression that converters from T to a Point
public class ToPointConverter<T> : IToPointConverter
{
public static ToPointConverter<T> Create(Func<T, Point> conversion)
{
return new ToPointConverter<T>(conversion);
}
private ToPointConverter(Func<T, Point> conversion)
{
_conversion = conversion;
}
private Func<T, Point> _conversion;
public Point Convert(T obj) => _conversion(obj);
Point IToPointConverter.Convert(object obj) => Convert((T)obj);
}
//The non-generic interface for the converter (so different closed generic types can be stored in the same dictionary, and have their Convert method called.)
public interface IToPointConverter
{
Point Convert(object obj);
}
//Just a standard structure to hold a location. You would use whatever native location class your framework has.
public struct Point
{
public int X;
public int Y;
}
//Some example kitty classes
public class KittyA
{
public Point Location { get; set; }
}
public class KittyB
{
public int X { get; set; }
public int Y { get; set; }
}
public class KittyC
{
public Point MyLocation { get; set; }
}
namespace Area
{
public class Rectangle
{
private double length;
private double width;
public Rectangle() { }
public Rectangle(double length, double width)
{
this.Length = length;
this.Width = width;
}
public double Length
{
get
{
return length;
}
set
{
length = value;
}
}
public double Width
{
get
{
return width;
}
set
{
width = value;
}
}
public double getArea()
{
return width * length;
}
public double getPerimeter()
{
return 2 * width + 2 * length;
}
public double getDiagonal()
{
return Math.Sqrt(Math.Pow(width, 2) + Math.Pow(length, 2));
}
I want to make sure I am using best practices with C# Objects. Please use the above example for reference.
1. Is it necessary that I type the first empty Constructor? In class the Instructor always did on each program but never really gave an answer as to why.
public Rectangle() { }
2. Inside my Custom Constructor Visual Studio generates it like this:
this.Length = length;
I know that the "this" keyword is not necessary the way it is typed, but in class the instructor sometimes changed it to lowercase like this:
this.length = length;
But sometimes he didn't change it. Which way is best practices?
And is the left side the actual Property? And then the right side is the field?
So it is, Property equals field?
3. And finally, in this case cant I just type my properties as:
public string Length { get; set; }
instead of the way Visual Studio generates with the return and value.
Sorry for the long post, I am tired of getting different answers at school and want one final answer on this, thanks.
I would suggest that your class look like this:
public class Rectangle
{
public Rectangle(double length, double width)
{
this.Length = length;
this.Width = width;
}
public double Length { get; set; }
public double Width { get; set; }
public double Area { get { return this.Width * this.Length; } }
public double Perimeter { get { return 2.0 * (this.Width + this.Length); } }
public double Diagonal { get { return Math.Sqrt(Math.Pow(this.Width, 2.0) + Math.Pow(this.Length, 2.0)); } }
}
See here for why you might want a blank constructor. To summarize, adding a non blank constructor will stop the compiler from generating a blank one for you (the compiler assumes that if you wanted it, you would have defined it with the other constructors you wrote). Some things, like serialization, will not work without a blank constructor, so that's a reason you might want to add one.
In my career, I've mostly seen people avoid using this in constructors. Maybe avoid isn't the right word, but unless it's unclear, they just didn't bother to put it there. This is probably too minor an issue to lose any sleep over.
UPDATE based on some of your comments
When you write
public Rectangle(double length, double width)
{
Length = length; //parameter length assigned to field length by virtue of property Length
}
you are assigning the parameter length to the property Length, which itself assigns the passed in value to the length private field. Since C# is case sensitive, Length and length aren't confused in any scenario, and you don't need to specify the this keyword.
Inside a method with a parameter called length, the language is assuming that you are referring to the parameter of the method when you type length. So if you try to do something like this:
public Rectangle(double length, double width)
{
length = length; //warning: Assignment made to same variable; did you mean to assign to something else
}
The compiler doesn't try and assume that you are assigning the property to the field, and this is just assigning the length parameter to itself. In this case, you would use the this keyword to tell the compiler that you want to assign the parameter length to the private field length, like this:
public Rectangle(double length, double width)
{
this.length = length; //no warning
}
END UPDATE
Yes, you could declare the property as just Property {get;set;}. This feature is only from C# 3.0 and is called auto-implemented properties (see this link). Before that you had to provide the implementation yourself.
I changed my class to this:
public class Rectangle
{
public Rectangle(double length, double width)
{
Length = length;
Width = width;
}
public double Length { get; set; }
public double Width { get; set; }
public double getArea()
{
return Width * Length;
}
public double getPerimeter()
{
return 2 * Width + 2 * Length;
}
public double getDiagonal()
{
return Math.Sqrt(Math.Pow(Width, 2) + Math.Pow(Length, 2));
}
}
If anyone has any other feedback on anything above that you recommend to change please give it, I catch on very fast and want to learn the correct way.
This is not exactly what I am working with but I hope it makes a clear example:
public abstract class Shape
{
public int Area;
public int Perimeter;
public class Polygon : Shape
{
public int Sides;
public Polygon(int a, int p, int s){
Area = a;
Perimeter = p;
Sides = s;
}
}
public class Circle : Shape
{
public int Radius;
public Circle(int r){
Area = 3.14*r*r;
Perimeter = 6.28*r;
Radius = r;
}
}
}
In the main function I would have something like this:
Shape[] ThisArray = new Shape[5];
ThisArray[0] = new Shape.Circle(5);
ThisArray[1] = new Shape.Polygon(25,20,4);
My problem is that when I deal with ThisArray, I can't access values other than Area and Perimeter. For example:
if (ThisArray[0].Area > 10)
//This statement will be executed
if (ThisArray[1].Sides == 4)
//This will not compile
How can I access Sides from ThisArray[1]? I could access it if I did something like
Shape.Polygon RandomSquare = new Shape.Polygon(25,20,4) but not if it is in an array of shapes.
If I recall correctly this could be accomplished in C++ by doing something like
Polygon->ThisArray[1].Sides (I forget what this is called) but I do not know how do this in C#
If I can't do what I am trying to do, how can I circumvent this problem?
Thank you for reading through what I intended to be short, any help is appreciated.
You should use casting:
(ThisArray[1] as Shape.Polygon).Sides
Note that you should make sure the underlying object instance actually IS a Polygon, otherwise this will raise an exception. You can do this by using something like:
if(ThisArray[1] is Shape.Polygon){
(ThisArray[1] as Shape.Polygon).Sides
}
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
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