I already make twice same bug in code like following:
void Foo(Guid appId, Guid accountId, Guid paymentId, Guid whateverId)
{
...
}
Guid appId = ....;
Guid accountId = ...;
Guid paymentId = ...;
Guid whateverId =....;
//BUG - parameters are swapped - but compiler compiles it
Foo(appId, paymentId, accountId, whateverId);
OK, I want to prevent these bugs, so I created strongly typed GUIDs:
[ImmutableObject(true)]
public struct AppId
{
private readonly Guid _value;
public AppId(string value)
{
var val = Guid.Parse(value);
CheckValue(val);
_value = val;
}
public AppId(Guid value)
{
CheckValue(value);
_value = value;
}
private static void CheckValue(Guid value)
{
if(value == Guid.Empty)
throw new ArgumentException("Guid value cannot be empty", nameof(value));
}
public override string ToString()
{
return _value.ToString();
}
}
And another one for PaymentId:
[ImmutableObject(true)]
public struct PaymentId
{
private readonly Guid _value;
public PaymentId(string value)
{
var val = Guid.Parse(value);
CheckValue(val);
_value = val;
}
public PaymentId(Guid value)
{
CheckValue(value);
_value = value;
}
private static void CheckValue(Guid value)
{
if(value == Guid.Empty)
throw new ArgumentException("Guid value cannot be empty", nameof(value));
}
public override string ToString()
{
return _value.ToString();
}
}
These structs are almost same, there is a lot of duplication of code. Isn't is?
I cannot figure out any elegant way to solve it except using class instead of struct. I would rather use struct, because of null checks, less memory footprint, no garbage collector overhead etc...
Do you have some idea how to use struct without duplicating code?
First off, this is a really good idea. A brief aside:
I wish C# made it easier to create cheap typed wrappers around integers, strings, ids, and so on. We are very "string happy" and "integer happy" as programmers; lots of things are represented as strings and integers which could have more information tracked in the type system; we don't want to be assigning customer names to customer addresses. A while back I wrote a series of blog posts (never finished!) about writing a virtual machine in OCaml, and one of the best things I did was wrapped every integer in the virtual machine with a type that indicates its purpose. That prevented so many bugs! OCaml makes it very easy to create little wrapper types; C# does not.
Second, I would not worry too much about duplicating the code. It's mostly an easy copy-paste, and you are unlikely to edit the code much or make mistakes. Spend your time solving real problems. A little copy-pasted code is not a big deal.
If you do want to avoid the copy-pasted code, then I would suggest using generics like this:
struct App {}
struct Payment {}
public struct Id<T>
{
private readonly Guid _value;
public Id(string value)
{
var val = Guid.Parse(value);
CheckValue(val);
_value = val;
}
public Id(Guid value)
{
CheckValue(value);
_value = value;
}
private static void CheckValue(Guid value)
{
if(value == Guid.Empty)
throw new ArgumentException("Guid value cannot be empty", nameof(value));
}
public override string ToString()
{
return _value.ToString();
}
}
And now you're done. You have types Id<App> and Id<Payment> instead of AppId and PaymentId, but you still cannot assign an Id<App> to Id<Payment> or Guid.
Also, if you like using AppId and PaymentId then at the top of your file you can say
using AppId = MyNamespace.Whatever.Id<MyNamespace.Whatever.App>
and so on.
Third, you will probably need a few more features in your type; I assume this is not done yet. For example, you'll probably need equality, so that you can check to see if two ids are the same.
Fourth, be aware that default(Id<App>) still gives you an "empty guid" identifier, so your attempt to prevent that does not actually work; it will still be possible to create one. There is not really a good way around that.
We do the same, it works great.
Yes, it's a lot of copy and paste, but that is exactly what code-generation is for.
In Visual Studio, you can use T4 templates for this. You basically write your class once and then have a template where you say "I want this class for App, Payment, Account,..." and Visual Studio will generate you one source code file for each.
That way you have one single source (The T4 template) where you can make changes if you find a bug in your classes and it will propagate to all your Identifiers without you having to think about changing all of them.
This has a nice side effect. You can have these overloads for an add:
void Add(Account account);
void Add(Payment payment);
However you cannot have overloads for the get:
Account Get(Guid id);
Payment Get(Guid id);
I always disliked this asymmetry. You have to do:
Account GetAccount(Guid id);
Payment GetPayment(Guid id);
With the above approach this is possible:
Account Get(Id<Account> id);
Payment Get(Id<Payment> id);
Symmetry achieved.
This is fairly easy to implement using record.
public readonly record struct UserId(Guid Id)
{
public override string ToString() => Id.ToString();
public static implicit operator Guid(UserId userId) => userId.Id;
}
The implicit operator allows us to use the strongly typed UserId as a regular Guid where applicable.
var id = Guid.NewGuid();
GuidTypeImportant(id); // ERROR
GuidTypeImportant(new UserId(id)); // OK
DontCareAboutGuidType(new UserId(id)); // OK
DontCareAboutGuidType(id); // OK
void GuidTypeImportant(UserId id) { }
void DontCareAboutGuidType(Guid id) { }
You might be able to use subclassing with a different programming language.
Related
I have class named "config" that have private string variable named "param".
I need to get from "config" class "param" variable sometimes as int type sometimes as bool type or string.
As I understand I need create 3 properties in config class,each property have to convert type, as follow:
The first property converts string to int, the second converts string to bool, the third property gets me the string value.
The class should look something like this:
class Config
{
private string param;
public int ParamAsInt
{
get
{
return int.Parse(param);
}
}
public bool ParamAsBool
{
get
{
return bool.Parse(param);
}
}
public string ParamAsString
{
get
{
return param;
}
}
}
But I don't know how can those properties be used in accordance to the variable type that I want to get out of class.
This code won't compile - int and such are reserved keywords and cannot be used as identifiers. You can either try naming your properties something like Int32Value, StringValue, etc., or try this:
public static implicit operator bool (Config config)
{
return bool.Parse(config.param);
}
public static implicit operator int (Config config)
{
return int.Parse(config.param);
}
This will allow for much cleaner code:
Config c = GetConfig("foo");
var isFeatureEnabled = false || c;
var spacing = 23 + GetConfig("bar");
You forgot to give your properties names. How would you expect to reference them? Something like this:
class Config
{
private string param;
public int ParamAsInt
{
get
{
return int.Parse(param);
}
}
public bool ParamAsBool
{
get
{
return bool.Parse(param);
}
}
public string ParamAsString
{
get
{
return param;
}
}
}
Note that I also fixed the casing in your calls to .Parse(). C# is case-sensitive. I also replaced the call to bool.TryParse() with bool.Parse(). The former (when used correctly, which this wasn't because it was missing a parameter) will only tell you if it is a bool, it won't tell you what value the bool actually has. (For example, bool.TryParse('false' out someBool) will return true.)
Of course, this code is a bit dangerous. You'll want to start with some more defensive programming to check those values. Basically, look up TryParse() and how to use it correctly. Something like this, for example:
public int ParamAsInt
{
get
{
var tmp = default(int);
if (int.TryParse(param, out tmp))
return tmp;
else
// do something else? throw a specific exception?
}
}
Additionally, what is the purpose of this code? It seems like a very rushed and poor design. For any given value of param (how is that even being set, by the way?) this just sort of randomly tries to expose typed properties for it. If you guess the correct one, you're still left with others that will throw exceptions. Surely there's a much cleaner way to accomplish what you're trying to do. So what are you trying to do?
I'm looking to use "phantom types" to implement type-safe identifiers. There's a question here about doing this in F#.
I'd like to do this in C#. How?
I've got a solution (which has problems), so I'll post it as a possible answer to see if anyone can improve it.
Why not make it a sealed class with its constructor private?
public sealed class Id<TDiscriminator>
{
private Id() { }
//some static methods
}
I've come up with the following:
struct Id<TDiscriminator>
{
private readonly Guid _id;
private Id(Guid id)
{
_id = id;
}
public Guid Value
{
get { return _id; }
}
public static Id<TDiscriminator> NewId()
{
return From(Guid.NewGuid());
}
public static Id<TDiscriminator> From(Guid id)
{
return new Id<TDiscriminator>(id);
}
public static readonly Id<TDiscriminator> Empty = From(Guid.Empty);
// Equality operators ellided...
}
...which I can use as follows:
class Order { /* empty */ }
class Customer { /* empty */ }
void Foo()
{
var orderId = Id<Order>.NewId();
var customerId = Id<Customer>.NewId();
// This doesn't compile. GOOD.
bool same = (orderId == customerId);
}
I don't particularly want concrete classes for the discriminator, because I don't want anyone instantiating them.
I could get around that by using an interface or an abstract class. Unfortunately, these can still be derived from and instantiated.
C# won't let you use a static class as a type argument. I can't say that I'm totally happy with the answers to that question, because the answers basically say "just because".
How about?
public sealed class Order
{
private Order() {}
}
public static sealed class Id<T>
{
// ...
}
I think that's exactly what you say. No one (except some special cases) can construct it and no one can inherit from it.
Well, as far as I could understand, you would like to provide a mechanism for distinguishing different types by a custom identifier object. I think you are almost near a working solution. In .NET when having a generic class, each substitution of the generic argument (or each unique combination of the generic arguments, if more than one) creates a unique type in the runtime. In your code Id<Order> and Id<Customer> are two distinct types. The NewId() method returns an instance of Id<Order> for the orderId and Id<Customer> for the customerId variables. The two types do not implement the == operator and therefore cannot be compared. Moreover, such comparison would be difficult to implement, since you cannot determine all possible uses of the Id<TDsicriminator> - you cannot guess what type will the TDsicriminator be substituted with.
1
A fast and simple solution will be to do this:
class Order { /* skipped */ }
class Customer { /* skipped */ }
void Foo()
{
var orderId = Id<Order>.NewId();
var customerId = Id<Customer>.NewId();
bool sameIds = (orderId.Value == customerId.Value); // true
bool sameObjects = orderId.Equals(customerId); // false
}
Since the Value properties are both of the Guid type, comparison is possible.
2
If you need however, to implement the == operator, or some sort of equality comparisons for instances of Id<TDisciminator>, the approach will be different. What comes up to my mind is the following:
public abstract class IdBase
{
public abstract Guid Value { get; protected set; }
public static bool operator == (IdBase left, IdBase right)
{
return left.Value == right.Value;
}
}
public sealed class Id<TDiscriminator> : IdBase
{
// your implementation here, just remember the override keyword for the Value property
}
Many people would not recommend the second approach though, since different implementations of IdBase may happen to have the same Value property (if you used the constructor that passes an existing ID). For instance:
var guid = Guid.NewGuid();
var customerID = Id<Customer>.From(guid);
var orderID = Id<Order>.From(guid);
Here (customerID == orderID) will then return true which is probably not what you want.
Shortly, in such a case, two different types will count as equal, which is a big logical mistake, so I'd stick to the first approach.
If you need Id<Customer>.Value to always be different than Id<Order>.Value, because of the different generic arguments (Customer is different than Order), then the following approach will work:
public sealed class Id<in TDiscriminator>
{
private static readonly Guid _idStatic = Guid.NewGuid();
private Id()
{
}
public Guid Value
{
get { return _idStatic; }
}
}
Notice the in keyword used here. This is applicable for .NET 4.0 where generics can be covariant and ensures that your class uses contravariant generics. (see http://msdn.microsoft.com/en-us/library/dd469487.aspx). In the above code, the _idStatic field will have a unique value for every different type supplied as a generic argument.
I hope this info is helpful.
I have a class library containing several structures each consisting of several value and reference types. Most of the value types are mandatory, a few value types and all reference types are optional. All structures are XmlSerializable (which is mandatory).
As far as the class library is targeted to mobile devices I want to reduce the memory footprint. My first idea was to use Nullable<T> for the value types, but this increases the memory size by 4 bytes per Nullable<T>. My second idea is to pack all optional value types into a separate structure that is only instantiated when any of its members is needed. But this would force me to implement IXmlSerializable on the "main" structure.
Are there any other approaches to "shrink" the structures?
[EDIT]
Beg your pardon for this bad question. I think I have to clarify some things and get more specific:
The class library is designed to serialize data info GPX (GPS Exchange Format). The structures are e.g. Waypoint or Track. They have mandatory fields as latitude, longitude etc. Optional fields are Vertical/Horizontal/Position Dilution of Precision, a description, a link.
The library is mainly targeted to Mobile devices such as PDAs. RAM is short, but plenty of non-volatile Memory is available.
Code examples cannot be shown as far as there are none. I want to think about several pitfalls before starting the implementation.
Here is a technique to aggressively reduce in memory overhead whilst allowing Xml Serialization.
Update: the orignal inline linked list idea is more efficient for 1 and 2 entries than a standard list with count construct but the use of fixed size optionals for zero, one and two cases is even more efficient.
Proviso:
This is predicated on you knowing that you really do need to shave the memory, as such
(since you haven't done any coding yet) this may well be a massively premature
optimization.
Also this design is predicated on the optional fields being very rare.
I use double as a 'placeholder' whatever format best allows you to represent the precision/units involved should be used.
public class WayPoint
{
// consumes IntPtr.Size fixed cost
private IOptional optional = OptionalNone.Default;
public double Latitude { get; set; }
public double Longitude { get; set; }
public double Vertical
{
get { return optional.Get<double>("Vertical") ?? 0.0; }
set { optional = optional.Set<double>("Vertical", value); }
}
[XmlIgnore] // need this pair for every value type
public bool VerticalSpecified
{
get { return optional.Get<double>("Vertical").HasValue; }
}
public void ClearVertical()
{
optional = optional.Clear<double>("Vertical");
}
public string Description // setting to null clears it
{
get { return optional.GetRef<string>("Description"); }
set { optional = optional.SetRef<string>("Description", value); }
}
// Horizontal, Position, DilutionOfPrecision etc.
}
The real heavy lifting is done here:
internal interface IOptional
{
T? Get<T>(string id) where T : struct;
T GetRef<T>(string id) where T : class;
IOptional Set<T>(string id, T value);
IOptional Clear(string id);
}
internal sealed class OptionalNone : IOptional
{
public static readonly OptionalNone Default = new OptionalNone();
public T? Get<T>(string id) where T : struct
{
return null;
}
public T GetRef<T>(string id) where T : class
{
return null;
}
public IOptional Set<T>(string id, T value)
{
if (value == null)
return Clear(id);
return new OptionalWithOne<T>(id, value);
}
public IOptional Clear(string id)
{
return this; // no effect
}
}
The fixed size ones become more interesting to write, there is no point writing these as structs as they would be boxed to be placed within the IOptional field within the WayPoint class.
internal sealed class OptionalWithOne<X> : IOptional
{
private string id1;
private X value1;
public OptionalWithOne(string id, X value)
{
this.id1 = id;
this.value1 = value;
}
public T? Get<T>(string id) where T : struct
{
if (string.Equals(id, this.id1))
return (T)(object)this.value1;
return null;
}
public T GetRef<T>(string id) where T : class
{
if (string.Equals(id, this.id1))
return (T)(object)this.value1;
return null;
}
public IOptional Set<T>(string id, T value)
{
if (string.Equals(id, this.id1))
{
if (value == null)
return OptionalNone.Default;
this.value1 = (X)(object)value;
return this;
}
else
{
if (value == null)
return this;
return new OptionalWithTwo<X,T>(this.id1, this.value1, id, value);
}
}
public IOptional Clear(string id)
{
if (string.Equals(id, this.id1))
return OptionalNone.Default;
return this; // no effect
}
}
Then for two (you can extend this idea as far as you want but as you can see the code gets unpleasant quickly.
internal sealed class OptionalWithTwo<X,Y> : IOptional
{
private string id1;
private X value1;
private string id2;
private Y value2;
public OptionalWithTwo(
string id1, X value1,
string id2, Y value2)
{
this.id1 = id1;
this.value1 = value1;
this.id2 = id2;
this.value2 = value2;
}
public T? Get<T>(string id) where T : struct
{
if (string.Equals(id, this.id1))
return (T)(object)this.value1;
if (string.Equals(id, this.id2))
return (T)(object)this.value2;
return null;
}
public T GetRef<T>(string id) where T : class
{
if (string.Equals(id, this.id1))
return (T)(object)this.value1;
if (string.Equals(id, this.id2))
return (T)(object)this.value2;
return null;
}
public IOptional Set<T>(string id, T value)
{
if (string.Equals(id, this.id1))
{
if (value == null)
return Clear(id);
this.value1 = (X)(object)value;
return this;
}
else if (string.Equals(id, this.id2))
{
if (value == null)
return Clear(id);
this.value2 = (Y)(object)value;
return this;
}
else
{
if (value == null)
return this;
return new OptionalWithMany(
this.id1, this.value1,
this.id2, this.value2,
id, value);
}
}
public IOptional Clear(string id)
{
if (string.Equals(id, this.id1))
return new OptionalWithOne<Y>(this.id2, this.value2);
if (string.Equals(id, this.id2))
return new OptionalWithOne<X>(this.id1, this.value1);
return this; // no effect
}
}
Before finally ending with the relatively inefficient
internal sealed class OptionalWithMany : IOptional
{
private List<string> ids = new List<string>();
// this boxes, if you had a restricted set of data types
// you could do a per type list and map between them
// it is assumed that this is sufficiently uncommon that you don't care
private List<object> values = new List<object>();
public OptionalWithMany(
string id1, object value1,
string id2, object value2,
string id3, object value3)
{
this.ids.Add(id1);
this.values.Add(value1);
this.ids.Add(id2);
this.values.Add(value2);
this.ids.Add(id3);
this.values.Add(value3);
}
public T? Get<T>(string id) where T : struct
{
for (int i= 0; i < this.values.Count;i++)
{
if (string.Equals(id, this.ids[i]))
return (T)this.values[i];
}
return null;
}
public T GetRef<T>(string id) where T : class
{
for (int i= 0; i < this.values.Count;i++)
{
if (string.Equals(id, this.ids[i]))
return (T)this.values[i];
}
return null;
}
public IOptional Set<T>(string id, T value)
{
for (int i= 0; i < this.values.Count;i++)
{
if (string.Equals(id, this.ids[i]))
{
if (value == null)
return Clear(id);
this.values[i] = value;
return this;
}
}
if (value != null)
{
this.ids.Add(id);
this.values.Add(value);
}
return this;
}
public IOptional Clear(string id)
{
for (int i= 0; i < this.values.Count;i++)
{
if (string.Equals(id, this.ids[i]))
{
this.ids.RemoveAt(i);
this.values.RemoveAt(i);
return ShrinkIfNeeded();
}
}
return this; // no effect
}
private IOptional ShrinkIfNeeded()
{
if (this.ids.Count == 2)
{
//return new OptionalWithTwo<X,Y>(
// this.ids[0], this.values[0],
// this.ids[1], this.values[1]);
return (IOptional)
typeof(OptionalWithTwo<,>).MakeGenericType(
// this is a bit risky.
// your value types may not use inhertence
this.values[0].GetType(),
this.values[1].GetType())
.GetConstructors().First().Invoke(
new object[]
{
this.ids[0], this.values[0],
this.ids[1], this.values[1]
});
}
return this;
}
}
OptionalWithMany could be written rather better than this but it gives you the idea.
With restricted type support you could do a global Key -> value map per type 'heap' like so:
internal struct Key
{
public readonly OptionalWithMany;
public readonly string Id;
// define equality and hashcode as per usual
}
Then simply store the list of Id's currently in use within OptionalToMany. Shrinking would be slightly more complex (but better from a type point of view since you would scan each global 'heap' till you found the matching entry and use the type of the heap to construct the OptionalWithTwo. This would allow polymorphism in the property values.
Regardless of the internals the primary benefit of this is that the public surface of the WayPoint class hides all this entirely.
You can then set up the class however you want for serialization though attributes, IXmlSerializable (which would remove the need for the annoying xxxSpecified properties).
I used strings as Id's for simplicity in my example.
If you really care about size and speed you should change the Id's to be enumerations. Given packing behaviour this won't save you much even if you can fit all needed values into a byte but it would give you compile time sanity checking. The strings are all compile time constants so occupy next to no space (but are slower for checking equality).
I urge you to only do something like this after you check that it is needed. The plus side is that this does not limit your xml serialization so you can mould it to whatever format you desire. Also the public face of the 'data packet' can be kept clean (except for the xxxSpecified junk).
If you want to avoid the xxxSpecified hassles and you know you have some 'out of band' values you can use the following trick:
[DefaultValue(double.MaxValue)]
public double Vertical
{
get { return optional.Get<double>("Vertical") ?? double.MaxValue; }
set { optional = optional.Set<double>("Vertical", value); }
}
public void ClearVertical()
{
optional = optional.ClearValue<double>("Vertical");
}
However the rest of you API must be capable of detecting these special values. In general I would say that the specified route is better.
If a particular set of properties become 'always available' on certain devices, or in certain modes you should switch to alternate classes where the properties for those are simple ones. Since the xml form will be identical this means they can interoperate simply and easily but memory usage in those cases will be much less.
If the number of these groups becomes large you may even consider a code-gen scenario (at runtime even, though this increases your support burden considerably)
For some serious fun:
apply Flyweight and store all instances in a bitmap? With a small memory device you don't need 4 byte pointers.
[Edit] With Flyweight, you can have a separate storage strategy for each field. I do not suggest to directly store the string value in the bitmap, but you could store an index.
The type is not stored in the bitmap, but in the unique object factory.
It is probably good to know that the XmlSerializer doesn't care about your internal object layout, it only cares about your public fields and properties. You can hide the internal memory optimizations behind your property accessors, and the XmlSerializer wouldn't even know.
For instance, if you know that you usually have only 2 references set, but on occasion more, you can store the two frequent ones as part of your main object, and hide the infrequent ones inside an object[] or ListDictionary or a specialized private class of your own making. However, be careful that each indirect container object also contains overhead, as it needs to be a reference type. Or when you have 8 nullable integers as part of your public contract, internally you could use 8 regular integers and a single byte containing the is-this-int-null status as its bits.
If you want to specialize even further, perhaps create specialized subclasses depending on the available data, you would have to go the route of IXmlSerializable, but usually that's not really needed.
You can do a couple of things:
Make sure to use the smallest type possible for a particular value. For example, if you look at the schema, dgpsStationType has a min value of 0, and a max of 1023. This can be stored as a ushort. Reduce the size of these items when possible.
Make sure that your fields are 4-byte aligned. The end resulting size of your structure will be some multiple of 4-bytes in size (assuming 32-bit). The default layout for a class has the items stored sequentially. If the fields are not packed correctly, the compiler will have wasted space making sure that your fields are 4-byte aligned. You can specify the layout explicitly using StructLayoutAttribute.
Bad Example: these fields in a class take up 12 bytes. The int must take up 4 contiguous bytes, and the other members must be 4-byte aligned.
public class Bad {
byte a;
byte b;
int c;
ushort u;
}
Better Example: these fields in a class take up 8 bytes. These fields are packed efficiently.
public class Better {
byte a;
byte b;
ushort u;
int c;
}
Reduce the size of your object graph. Each reference type takes up 8 bytes of overhead. If you've got a deep graph, that's a lot of overhead. Pull everything you can into functions that operate on data in you main class. Think more 'C' like, and less OOD.
Its still a good idea to lazy-load some optional parameters, but you should draw your line clearly. Create 1 or maybe 2 sets of 'optional' values that can be loaded or null. Each set will mandate a reference type, and its overhead.
Use structs where you can. Be careful of value-type semantics though, they can be tricky.
Consider not implementing ISerializable. Interface methods are by definition virtual. Any class with virtual methods contains a reference to a vtable (another 4 bytes). Instead implement xml serialization manually in an external class.
Build your own serializing in order to minimize your structure. And serialize to binary and not xml.
Something along the lines of:
internal void Save(BinaryWriter w)
{
w.Write(this.id);
w.Write(this.name);
byte[] bytes = Encoding.UTF8.GetBytes(this.MyString);
w.Write(bytes.Length);
w.Write(bytes);
w.Write(this.tags.Count); // nested struct/class
foreach (Tag tag in this.tags)
{
tag.Save(w);
}
}
and have a constructor which builds it back up
public MyClass(BinaryReader reader)
{
this.id = reader.ReadUInt32();
etc.
}
Some sort of binary serialization will often do much better than XML serialization. You'll have to try it out for your specific data structures to see if you gain much.
Check out MSDN an example using BinaryFormatter.
So I've got a whole bunch of options, every different page/tab can have their own local options. We'll have maybe 10-15 pages tabs open tops. I need to implement a way to show the global defaults, weather the all the tabs have consistent values. I'm working on the model/viewmodel portion of a WPF app.
I'd love to find a way that is more elegant since I'm having to cut and past roughly the same code 20+ times and just change property names. Maybe this is the problem Dynamics solve, but right now this feels both wrong and painful.
Here is an example of my current solution:
public class Foo
{
private bool fooVar1;
private bool fooVar2;
//lots of these
private decimal fooVar23;
public Foo()
{
}
public bool FooVar1
{
get;
set;
}
//you get the picture...
}
public class FooMonitor
{
private Foo defaultFoo;
private List<Foo> allFoos;
public FooMonitor(Foo DefaultFoo)
{
defaultFoo = DefaultFoo;
}
public void AddFoo(Foo newFoo)
{
allFoos.Add(newFoo);
}
public void AddFoo(Foo oldFoo)
{
allFoos.Remove(oldFoo);
}
public bool IsFooVar1Consistent
{
get
{
Foo[] tempFoos = allFoos.ToArray();
foreach (Foo tempFoo in tempFoos)
{
if (tempFoo.FooVar1 != defaultFoo.FooVar1) return false;
}
return true;
}
}
}
Or am I approaching this problem entirely incorrectly.
As I'm writing this question (After about 2000 lines of code) I'm thinking of how I read that WPF itself implements Dictionary look ups that crawl up to the parent to see if a Property is present and what the value should be.
Well, for a start you are defining both backing fields which will never be used and automatic properties. This is enough for a simple bool property:
public bool FooVar1 { get; set; }
No need for the private field. This greatly reduces the number of lines in your example.
I'd love to find a way that is more
elegant since I'm having to cut and
past roughly the same code 20+ times
and just change property names.
Code generators exist for exactly this purpose. But if you don't want to go that route, you can shorten your code to this:
return allFoos.All(foo => foo.FooVar1 == defaultFoo.FooVar1);
I'm not quite sure what the question is, but if you're looking for some way to unify the IsFoorVarXConsistent code, you could do it using reflection or by passing in an expression:
public bool IsConsistent(Func<Foo, bool> property)
{
foreach (Foo tempFoo in allFoos)
{
if (property(tempFoo) != property(defaultFoo))
return false;
}
return true;
}
Called like this:
bool is1Consistent = IsConsistent(f => f.FooVar1);
As shown this will only work for boolean properties. To extend it to other types, we can make it generic in the property type. However, in this case we cannot use != to test for inequality because not all types define a != operator. Instead we can use the .Equals method and the ! operator:
public bool IsConsistent<T>(Func<Foo, T> property)
where T : struct
{
foreach (Foo tempFoo in allFoos)
{
if (!property(tempFoo).Equals(property(defaultFoo)))
return false;
}
return true;
}
The where T : struct clause restricts this to value types like int, bool and decimal. In particular it will not work on strings. Removing the where constraint allows it to work on strings and other reference types, but creates the possibility of property(tempFoo) being null, which would cause a NullReferenceException when we called .Equals on it. So if you remove the value types constraint then you will need to add error handling for this scenario.
The point of const-correctness is to be able to provide a view of an instance that can't be altered or deleted by the user. The compiler supports this by pointing out when you break constness from within a const function, or try to use a non-const function of a const object. So without copying the const approach, is there a methodology I can use in C# that has the same ends?
I'm aware of immutability, but that doesn't really carry over to container objects to name but one example.
I've come across this issue a lot of times too and ended up using interfaces.
I think it's important to drop the idea that C# is any form, or even an evolution of C++. They're two different languages that share almost the same syntax.
I usually express 'const correctness' in C# by defining a read-only view of a class:
public interface IReadOnlyCustomer
{
String Name { get; }
int Age { get; }
}
public class Customer : IReadOnlyCustomer
{
private string m_name;
private int m_age;
public string Name
{
get { return m_name; }
set { m_name = value; }
}
public int Age
{
get { return m_age; }
set { m_age = value; }
}
}
To get the benefit of const-craziness (or pureness in functional programming terms), you will need to design your classes in a way so they are immutable, just like the String class of c# is.
This approach is way better than just marking an object as readonly, since with immutable classes you can pass data around easily in multi-tasking environments.
I just wanted to note for you that many of the System.Collections.Generics containers have an AsReadOnly method which will give you back an immutable collection.
C# doesn't have such feature. You can pass argument by value or by reference. Reference itself is immutable unless you specify ref modifier. But referenced data isn't immutable. So you need to be careful if you want to avoid side effects.
MSDN:
Passing Parameters
Interfaces are the answer, and are actually more powerful than "const" in C++. const is a one-size-fits-all solution to the problem where "const" is defined as "doesn't set members or call something that sets members". That's a good shorthand for const-ness in many scenarios, but not all of them. For example, consider a function that calculates a value based on some members but also caches the results. In C++, that's considered non-const, although from the user's perspective it is essentially const.
Interfaces give you more flexibility in defining the specific subset of capabilities you want to provide from your class. Want const-ness? Just provide an interface with no mutating methods. Want to allow setting some things but not others? Provide an interface with just those methods.
Agree with some of the others look at using readonly fields that you initialize in the constructor, to create immutable objects.
public class Customer
{
private readonly string m_name;
private readonly int m_age;
public Customer(string name, int age)
{
m_name = name;
m_age = age;
}
public string Name
{
get { return m_name; }
}
public int Age
{
get { return m_age; }
}
}
Alternatively you could also add access scope on the properties, i.e. public get and protected set?
public class Customer
{
private string m_name;
private int m_age;
protected Customer()
{}
public Customer(string name, int age)
{
m_name = name;
m_age = age;
}
public string Name
{
get { return m_name; }
protected set { m_name = value; }
}
public int Age
{
get { return m_age; }
protected set { m_age = value; }
}
}
The const keyword can be used for compile time constants such as primitive types and strings
The readonly keyword can be used for run-time constants such as reference types
The problem with readonly is that it only allows the reference (pointer) to be constant. The thing referenced (pointed to) can still be modified. This is the tricky part but there is no way around it. To implement constant objects means making them not expose any mutable methods or properties but this is awkward.
See also Effective C#: 50 Specific Ways to Improve Your C# (Item 2 - Prefer readonly to const.)