Differences with BinaryFormatter - c#

I am trying to change the serializer in an existing WCF net.tcp project that uses shared entities on client & server. I am having a hard time figuring out protobuf-net(V2480)
The chart here says I can serialize private members but cannot find documentation to do that, is it possible without attributes? How do I enable graph mode(As Reference) as explained here
Will that solve the issue of protobuf triggering my changed items flag? For example I have a class
public enum FirstEnum
{
First = 0,
Second,
Third
}
public enum AnotherEnum
{
AE1 = 0,
AE2,
AE3
}
[Serializable()]
public class SomeClass
{
public int SomeClassId { get; set; }
public FirstEnum FEnum { get; set; }
public AnotherEnum AEnum { get; set; }
string thing;
public string Thing
{
get{return thing;}
set
{
if (string.IsNullOrEmpty(value))
throw new ArgumentNullException("Thing");
thing = value;
}
}
private decimal firstAmount;
public decimal FirstAmount
{
get{return firstAmount;}
set
{
if (value != firstAmount)
{
firstAmount = value;
changedItems.Add("FirstAmount changed");
}
}
}
private decimal secondAmount;
public decimal SecondAmount
{
get { return secondAmount; }
set
{
if (value != secondAmount)
{
secondAmount = value;
changedItems.Add("SecondAmount changed");
}
}
}
public decimal ThirdAmount { get { return SecondAmount - FirstAmount; } }
public DateTime? SomeDate { get; set; }
private List<string> changedItems = new List<string>();
public List<string> ChangedItems
{
get { return changedItems; }
}
public int PrivateSet { get; private set; }
public SomeClass() { }
public SomeClass(decimal first, decimal second)
{
FirstAmount = first;
SecondAmount = second;
}
public void ClearChangedItems()
{
changedItems.Clear();
}
When I deserialize it with (1000 items)
var model = CreateModel();
items = (List<SomeClass>)model.Deserialize(returnStream, null, typeof(List<SomeClass>));
2012-04-06 09:14:28.1222|DEBUG|ProtobufTEsts.Form1|ProtoBuf Number of changed items : 1000
With BinaryForrmatter
System.Runtime.Serialization.Formatters.Binary.BinaryFormatter binaryFormatter = new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter();
items = (List<SomeClass>)binaryFormatter.Deserialize(returnStream);
2012-04-06 09:14:28.1662|DEBUG|ProtobufTEsts.Form1|BinaryFormatter Number of changed items : 0
Is there a way to get protobuf to behave like the binaryFormatter but preserve the performance of protobuf?
How to allow for private serialization, this fails
public static TypeModel CreateModel()
{
RuntimeTypeModel model = TypeModel.Create();
///var metaType = RuntimeTypeModel.Default.Add(typeof(SomeClass), false);
model.Add(typeof(SomeClass), false)
.Add(1, "SomeClassId")
.Add(2, "FEnum")
.Add(3, "AEnum")
.Add(4, "Thing")
.Add(5, "FirstAmount")
.Add(6, "SecondAmount")
.Add(7, "SomeDate")
.Add(8, "PrivateSet");
TypeModel compiled = model.Compile();
return compiled;
}

Ah, I understand the issue now; this line is problematic:
TypeModel compiled = model.Compile();
return compiled;
If you use Compile(), it creates a formal assembly (in memory) that has to obey the usual rules of assemblies, and in particular: member accessibility. This means it can't access your private sertter.
Instead, use:
model.CompileInPlace();
return model;
This performs a partial compilation, but continues using DynamicMethod. This cheeky little critter has options to spoof its way past accessibility rules (much like reflection can), so it can continue to use the private setter.
Note that the model is also compiled-in-place (at a more granular level) on as as-needed basis, so this call to CompileInPlace is not strictly necessary, but helps do everything up-front an in advance.
For completeness, there is an additional Compile(string,string) overload that can be used to produce a separate serialization dll on disk, that can be referenced and used without any meta-programming at runtime.

Yes protobuf-net can serialize private fields, and do so without attributes. I'm not at a PC, so this may need tweaking:
var metaType = RuntimeTypeModel.Default.Add(typeof(SomeClass), false);
// for each field in a known order
metaType.Add(fieldName, someUniqueTag);
In attribute-driven usage, there is also ImplicitFields.AllFields which would automatically configure it for the usage you intend, but I haven't yet added an ImplicitFields helper method to MetaType. I will add that to my list!
Note: tag (=field) numbers are important to protobuf and it must be possible to reproduce the same number mappings when you deserialize.
Another option you might want to consider is (de)serialization callbacks, which allow you to know that it is currently serializing/deserializing (via before/after method invokes). This can be another way of disabling side-effects for an interval such as deserialization.

Related

String Object with fixed length C#

I have a class wherein I want to use Strings with a fixed size.
The reason for the fixed size is that the class "serializes" into a textfile
with values with a fixed length. I want to avoid to write foreach value a guard clause and instead have the class handle this.
So I have round about 30 properties which would look like this
public String CompanyNumber
{
get
{
return m_CompanyNumber.PadLeft(5, ' ');
}
set
{
if (value.Length > 5)
{
throw new StringToLongException("The CompanyNumber may only have 5 characters", "CompanyNumber");
}
m_CompanyNumber = value;
}
}
I would like to have a String that handles this by itself. Currently I have the following:
public class FixedString
{
String m_FixedString;
public FixedString(String value)
{
if (value.Length > 5)
{
throw new StringToLongException("The FixedString value may consist of 5 characters", "value");
}
m_FixedString= value;
}
public static implicit operator FixedString(String value)
{
FixedString fsv = new FixedString(value);
return fsv;
}
public override string ToString()
{
return m_FixedString.PadLeft(5,' ');
}
}
The problem I have with this solution is that I can't set the String length at "compile time".
It would be ideal if it would look something like this in the end
public FixedString<5> CompanyNumber { get; set; }
I would go further back and question the design. This solution mashes together two concerns--internal application state and storage format--that should remain separate.
You could decorate each string property with a MaxLengthAttribute and then validate to that, but your code for (de)serializing from your storage format should be completely separate. It could use the same attributes to glean the field lengths for storage (if that happy coincidence holds) but your internal representation shouldn't "know" about the storage details.
Make FixedString take the size as a constructor parameter, but not the value itself
public class FixedString
{
private string value;
private int length;
public FixedString(int length)
{
this.length = length;
}
public string Value
{
get{ return value; }
set
{
if (value.Length > length)
{
throw new StringToLongException("The field may only have " + length + " characters");
}
this.value = value;
}
}
}
Initilise it with your class, and just set the Value when it changes
public class MyClass
{
private FixedString companyNumber = new FixedString(5);
public string CompanyNumber
{
get{ return companyNumber.Value; }
set{ companyNumber.Value = value; }
}
}
You can define an Interface like this:
public interface ILength
{
int Value { get; }
}
Some struct that implements the interface:
public struct LengthOf5 : ILength
{
public int Value { get { return 5; } }
}
public struct LengthOf10 : ILength
{
public int Value { get { return 10; } }
}
And then:
public class FixedString<T> where T : struct, ILength
{
String m_FixedString;
public FixedString(String value)
{
if (value.Length > default(T).Value)
{
throw new ArgumentException("The FixedString value may consist of " + default(T).Value + " characters", "value");
}
m_FixedString = value;
}
public static implicit operator FixedString<T>(String value)
{
FixedString<T> fsv = new FixedString<T>(value);
return fsv;
}
public override string ToString()
{
return m_FixedString;
}
}
To be honest I don't know if i like this solution but is the best I can think to solve your problem.
You could put an attribute over your String property and then validate all of them at some time (maybe a button click or something like that).
using System.ComponentModel.DataAnnotations;
public class MyObject
{
[StringLength(5)]
public String CompanyName { get; set; }
}
public void Save(MyObject myObject)
{
List<ValidationResult> results = new List<ValidationResult>();
ValidationContext context = new ValidationContext(myObject, null, null);
bool isValid = Validator.TryValidateObject(myObject, context, results);
if (!isValid)
{
foreach (ValidationResult result in results)
{
// Do something
}
}
}
More about DataAnnotations here.
I think your original idea of creating a string of fixed length is a very valid one, strictly modelling the domain of your system and using the type system to verify it is an idea that I find very appealing. Questions like this seem to come up very often within the F# community.
Unfortunately something like the type definition you suggested (FixedString<5>) is not possible in the context of .NET.
Some of the answers so far have talked about workarounds, alternatives or other ideas, I'd like to instead answer why you can't do what you originally requested in C#.
First of all, lets look at how you could do this in an arbitrary language:
Templates: You could do something like this in C++ using the template system. As Eric Lippert puts it in his article on the differences between generics and templates, "You can think of templates as a fancy-pants search-and-replace mechanism" (https://blogs.msdn.microsoft.com/ericlippert/2009/07/30/whats-the-difference-part-one-generics-are-not-templates/).
.NET generics are, in many ways, far simpler by comparison. Generic types are allow you to parametrise over types but not over values and open types are resolved at runtime whereas templates are an entirely compile time construct.
Dependent Types: A few languages support a feature called dependent types (https://en.wikipedia.org/wiki/Dependent_type). This allows you to define types that depend upon values. Many languages that support this feature are geared toward theorem proving rather than general purpose development.
Idris is perhaps unusual in being a general purpose language under active development (albeit a little known one) which does support this feature (see http://www.idris-lang.org/).
C#
C# does not support either of these features so, unfortunately, you can't solve this problem in a way that can be rigorously verified by the compiler.
I think there are plenty of good suggestions covered here for how you might implement something like this in C# but they all boil down to run-time verification.

Prototype pattern: ensure clone is in a valid state

LogEvent represents information like log level, message, user, process name, ...
Some of these properties' values require pretty much effort for generation, e. g. the process name. Those properties' generated values are usually not changed, BUT despite this fact it should be possible to change them.
I considered the prototype pattern starting with a protoype, whose generic properties are pre-allocated. The protoype stays the same object during the lifetime of the application, but its properties' values might change as described above. New LogEvent objects should use the current prototype's values, objects created before the change should continue using the old values, that means, referencing the prototype from the "real" LogEvent object is not an option.
However the "real" LogEvent requires some properties to be not null, whereas this requirement is not useful for the prototype. I would like to prevent invalid objects of LogEvent. However if I use usual protoype pattern I would have to add a constructor to create the prototype, but this constructor would not create a valid object and I want to avoid, that an invalid object (the prototype itself or a clone of it) is used accidentally.
I spent some time on searching a solution, but the approaches listed below are pretty ugly. I hope, that there is an elegant solution. Meanwhile I tend to option 3, because 1 and 2 do not seem to be clean.
General structure
public interface ILogEvent
{
string PreAllocatedProperty1 { get; set; }
string PreAllocatedProperty2 { get; set; }
string IndividualProperty1 { get; set; }
string IndividualProperty2 { get; set; }
}
Option 1
Pros
LogEventPrototype can not be used as ILogEvent.
properties do not have to be declared in multiple classes
Cons
properties have to be mapped manually
static methods => interface for prototypes not possible
Code
class LogEventPrototype
{
public string PreAllocatedProperty1 { get; set; }
public string PreAllocatedProperty2 { get; set; }
public string IndividualProperty1 { get; set; }
public string IndividualProperty2 { get; set; }
public LogEventPrototype() { GeneratePreAllocatedProperties(); }
private void GeneratePreAllocatedProperties()
{
// if you invoke the helper functions later again,
// they might return different results (e. g.: user identity, ...)
PreAllocatedProperty1 = Helper.ComplexFunction();
PreAllocatedProperty2 = Helper.AnotherComplexFunction();
}
}
class LogEvent : LogEventPrototype, ILogEvent
{
// just for creating the prototype, object will be in an INVALID state
private LogEvent() : base() { }
// object will be in a VALID state
public LogEvent(string individualProperty2)
: this()
{
if (individualProperty2 == null)
throw new ArgumentNullException();
IndividualProperty2 = individualProperty2;
}
public static LogEvent FromPrototype(LogEventPrototype prototype)
{
// clone manually
return new LogEvent(prototype.IndividualProperty2)
{
IndividualProperty1 = prototype.IndividualProperty1,
PreAllocatedProperty1 = prototype.PreAllocatedProperty1,
PreAllocatedProperty2 = prototype.PreAllocatedProperty2
};
}
}
Option 2
Similar to option 1, but:
Pros
it is "ensured", that LogEventPrototype is never instantiated, it is just used as return type
no manual mapping
Cons: It seems to be hacky.
class LogEventPrototype
{
// properties ... (same as in option 1)
protected LogEventPrototype()
{
GeneratePreAllocatedProperties();
}
}
class LogEvent : LogEventPrototype, ILogEvent
{
// constructors same as in option 1; FromPrototype() removed
public static LogEventPrototype CreateProtoype()
{
return new LogEvent();
}
public static LogEvent FromPrototype(LogEventPrototype prototype)
{
if(prototype.IndividualProperty2 == null)
throw new ArgumentException();
return (LogEvent)prototype;
}
public static LogEventPrototype CreateProtoype()
{
return new LogEvent();
}
}
Option 3
Do not use a dedicated class for prototypes, but make the LogEvent constructor public and risk invalid LogEvent objects. Use a Validate() method instead and hope, that a client does not forget to use it.

Is there anyway to reconstruct an object inside itself?

I have a simple class that is intended for options of an winforms application. There should be a method that reset options to their default values. I know I can add a separate method to take care of this, but the code will be huge (If I add more options to the class) :
public SensorOptions()
{
ShowLabelMax = ShowLabelMin = ShowLabelAvr = ShowReceivedTextBox = true;
ChartMaxValue = 140;
ChartMinValue = -40;
ShowChartMinValue = ShowChartMaxValue = ShowChartAvrValue = ShowChartAvrLine = true;
LogFolder = Environment.SpecialFolder.MyDocuments.ToString();
LoggingEnabled = true;
}
public void ResetOptions()
{
this = new SensorOptions(); //can not do. 'this' is read-only
}
I mean I can copy/paste the code from constructor into ResetOptions() method. But is there any smarter ways to achieve this?
You cannot assign this because you may have references to this instance of your class in your program. If you could re-construct the object by re-assigning this, it would mean that all references to the old instance of the class become invalid.
No matter how many options you have in your class, you initialize each of them one or the other way (because you mention default value in your question - so you need to assign that default value somewhere at least once, probably in the constructor). Therefore, the solution to your problem is simple - move all initializers to the separate method and call it in the constructor, and then also call it every time you need to reset your options to their default values.
If any of your options are not assigned a default value explicitly, and use system default and you don't want to write option=default(optionType) for each option, you can use reflection to enumerate all fields/properties in that class and assign default values to them, like this:
public static object GetDefault(Type type)
{
if(type.IsValueType) return Activator.CreateInstance(type);
return null;
}
foreach(var field in this.GetType().GetFields())
field.SetValue(this, GetDefault(field.FieldType));
foreach(var prop in this.GetType().GetProperties())
prop.SetValue(this, GetDefault(prop.PropertyType));
Move all of the code from the constructor into the ResetOptions method, then in your constructor call the ResetOptions method. Your initialisiation code is only in one place then.
You have very simple architecture for your situation. In my opinion it would be better to apply a trick for this:
you have class for holding all your options (pseudo code):
class AllOptionsBackstage
{
public bool ShowLabelMax { get; set; }
public bool ShowLabelMin { get; set; }
public bool ShowLabelAvr { get; set; }
public AllOptionsBackstage()
{
// apply default values here
}
}
.....
class MyOptions
{
private AllOptionsBackstage _options;
public MyOptions()
{
Reset();
}
public bool ShowLabelMax
{
get{ return _options.ShowLabelMax; }
set{ _options.ShowLabelMax = value; }
}
public bool ShowLabelMin
{
get{return _options.ShowLabelMin;}
set{_options.ShowLabelMin=value; }
}
public bool ShowLabelAvr
{
get{ return _options.ShowLabelAvr;}
set{ _options.ShowLabelAvr = value; }
}
public void Reset()
{
_options = new AllOptionsBackstage(); // will reset all your options to default
}
}

Looking for a short & simple example of getters/setters in C#

I am having trouble understanding the concept of getters and setters in the C# language. In languages like Objective-C, they seem an integral part of the system, but not so much in C# (as far as I can tell). I have read books and articles already, so my question is, to those of you who understand getters & setters in C#, what example would you personally use if you were teaching the concept to a complete beginner (this would include as few lines of code as possible)?
I think a bit of code will help illustrate what setters and getters are:
public class Foo
{
private string bar;
public string GetBar()
{
return bar;
}
public void SetBar(string value)
{
bar = value;
}
}
In this example we have a private member of the class that is called bar. The GetBar() and SetBar(string value) methods do exactly what they are named - one retrieves the bar member, and the other sets its value.
In C# 1.1 and later, you have properties. The basic functionality is also the same:
public class Foo
{
private string bar;
public string Bar
{
get { return bar; }
set { bar = value; }
}
}
The private member bar is not accessible outside the class, but the public Bar is, and it has two accessors: get, which returns the private member just as the GetBar() example above, and also a set, which corresponds to the SetBar(string value) method in the aforementioned example.
Starting with C# 3.0 and above, the compiler was optimized to the point that such properties do not need to be explicitly given a private member as their source. The compiler automatically generates a private member of that type and uses it as a source of a property.
public class Foo
{
public string Bar { get; set; }
}
What the code shows is an automatic property that has a private member generated by the compiler. You don't see the private member, but it is there. This also introduced a couple of other issues - mainly with access control. In C# 1.1 and 2.0, you could omit the get or set portion of a property entirely:
public class Foo
{
private string bar;
public string Bar
{
get { return bar; }
}
}
Giving you the chance to restrict how other objects interact with the Bar property of the Foo class. But from C# 3.0 to before 6.0, if you chose to use automatic properties, you would have to specify the access to the property as follows to emulate that behavior:
public class Foo
{
public string Bar { get; private set; }
}
The set accessor would still exist, but only the class itself could use it to set Bar to some value, and anyone could still get the value.
Thankfully, starting in C# 6.0, properties can be made read- or write-only again by simply omitting the property's get or set respectively (not to be confused with the readonly keyword):
public class Foo
{
// Read-only property
public string Bar { get; }
// Write-only property (less common)
public string Baz { set; }
}
In C#, Properties represent your Getters and Setters.
Here's an example:
public class PropertyExample
{
private int myIntField = 0;
public int MyInt
{
// This is your getter.
// it uses the accessibility of the property (public)
get
{
return myIntField;
}
// this is your setter
// Note: you can specify different accessibility
// for your getter and setter.
protected set
{
// You can put logic into your getters and setters
// since they actually map to functions behind the scenes
if (DoSomeValidation(value))
{
// The input of the setter is always called "value"
// and is of the same type as your property definition
myIntField = value;
}
}
}
}
You would access this property just like a field. For example:
PropertyExample example = new PropertyExample();
example.MyInt = 4; // sets myIntField to 4
Console.WriteLine( example.MyInt ); // prints 4
A few other things to note:
You don't have to specifiy both a getter and a setter, you can omit either one.
Properties are just "syntactic sugar" for your traditional getter and setter. The compiler will actually build get_ and set_ functions behind the scenes (in the compiled IL) and map all references to your property to those functions.
My explanation would be following. (It's not so short, but it's quite simple.)
Imagine a class with a variable:
class Something
{
int weight;
// and other methods, of course, not shown here
}
Well, there is a small problem with this class: no one can see the weight. We could make weight public, but then everyone would be able to change the weight at any moment (which is perhaps not what we want). So, well, we can do a function:
class Something
{
int weight;
public int GetWeight() { return weight; }
// and other methods
}
This is already better, but now everyone instead of plain something.Weight has to type something.GetWeight(), which is, well, ugly.
With properties, we can do the same, but the code stays clean:
class Something
{
public int weight { get; private set; }
// and other methods
}
int w = something.weight // works!
something.weight = x; // doesn't even compile
Nice, so with the properties we have finer control over the variable access.
Another problem: okay, we want the outer code to be able to set weight, but we'd like to control its value, and not allow the weights lower than 100. Moreover, there are is some other inner variable density, which depends on weight, so we'd want to recalculate the density as soon as the weight changes.
This is traditionally achieved in the following way:
class Something
{
int weight;
public int SetWeight(int w)
{
if (w < 100)
throw new ArgumentException("weight too small");
weight = w;
RecalculateDensity();
}
// and other methods
}
something.SetWeight(anotherSomething.GetWeight() + 1);
But again, we don't want expose to our clients that setting the weight is a complicated operation, it's semantically nothing but assigning a new weight. So the code with a setter looks the same way, but nicer:
class Something
{
private int _w;
public int Weight
{
get { return _w; }
set
{
if (value < 100)
throw new ArgumentException("weight too small");
_w = value;
RecalculateDensity();
}
}
// and other methods
}
something.Weight = otherSomething.Weight + 1; // much cleaner, right?
So, no doubt, properties are "just" a syntactic sugar. But it makes the client's code be better. Interestingly, the need for property-like things arises very often, you can check how often you find the functions like GetXXX() and SetXXX() in the other languages.
Most languages do it this way, and you can do it in C# too.
public void setRAM(int RAM)
{
this.RAM = RAM;
}
public int getRAM()
{
return this.RAM;
}
But C# also gives a more elegant solution to this:
public class Computer
{
int ram;
public int RAM
{
get
{
return ram;
}
set
{
ram = value; // value is a reserved word and it is a variable that holds the input that is given to ram ( like in the example below )
}
}
}
And later access it with:
Computer comp = new Computer();
comp.RAM = 1024;
int var = comp.RAM;
For newer versions of C# it's even better:
public class Computer
{
public int RAM { get; set; }
}
and later:
Computer comp = new Computer();
comp.RAM = 1024;
int var = comp.RAM;
C# introduces properties which do most of the heavy lifting for you...
ie
public string Name { get; set; }
is a C# shortcut to writing...
private string _name;
public string getName { return _name; }
public void setName(string value) { _name = value; }
Basically getters and setters are just means of helping encapsulation. When you make a class you have several class variables that perhaps you want to expose to other classes to allow them to get a glimpse of some of the data you store. While just making the variables public to begin with may seem like an acceptable alternative, in the long run you will regret letting other classes manipulate your classes member variables directly. If you force them to do it through a setter, you can add logic to ensure no strange values ever occur, and you can always change that logic in the future without effecting things already manipulating this class.
ie
private string _name;
public string getName { return _name; }
public void setName(string value)
{
//Don't want things setting my Name to null
if (value == null)
{
throw new InvalidInputException();
}
_name = value;
}
well here is common usage of getter setter in actual use case,
public class OrderItem
{
public int Id {get;set;}
public int quantity {get;set;}
public int Price {get;set;}
public int TotalAmount {get {return this.quantity *this.Price;}set;}
}
This would be a get/set in C# using the smallest amount of code possible. You get auto-implemented properties in C# 3.0+.
public class Contact
{
public string Name { get; set; }
}
As far as I understand getters and setters are to improve encapsulation.
There is nothing complex about them in C#.
You define a property of on object like this:
int m_colorValue = 0;
public int Color
{
set { m_colorValue = value; }
get { return m_colorValue; }
}
This is the most simple use. It basically sets an internal variable or retrieves its value.
You use a Property like this:
someObject.Color = 222; // sets a color 222
int color = someObject.Color // gets the color of the object
You could eventually do some processing on the value in the setters or getters like this:
public int Color
{
set { m_colorValue = value + 5; }
get { return m_colorValue - 30; }
}
if you skip set or get, your property will be read or write only. That's how I understand the stuff.
Simple example
public class Simple
{
public int Propery { get; set; }
}
Getters and Setters in C# are something that simplifies the code.
private string name = "spots";
public string Name
{
get { return name; }
set { name = value; }
}
And calling it (assume we have a person obj with a name property):
Console.WriteLine(Person.Name); //prints "spots"
Person.Name = "stops";
Console.Writeline(Person.Name); //prints "stops"
This simplifies your code. Where in Java you might have to have two methods, one to Get() and one to Set() the property, in C# it is all done in one spot. I usually do this at the start of my classes:
public string foobar {get; set;}
This creates a getter and setter for my foobar property. Calling it is the same way as shown before. Somethings to note are that you don't have to include both get and set. If you don't want the property being modified, don't include set!
Internally, getters and setters are just methods. When C# compiles, it generates methods for your getters and setters like this, for example:
public int get_MyProperty() { ... }
public void set_MyProperty(int value) { ... }
C# allows you to declare these methods using a short-hand syntax. The line below will be compiled into the methods above when you build your application.
public int MyProperty { get; set; }
or
private int myProperty;
public int MyProperty
{
get { return myProperty; }
set { myProperty = value; } // value is an implicit parameter containing the value being assigned to the property.
}
This is a basic example of an object "Article" with getters and setters:
public class Article
{
public String title;
public String link;
public String description;
public string getTitle()
{
return title;
}
public void setTitle(string value)
{
title = value;
}
public string getLink()
{
return link;
}
public void setLink(string value)
{
link = value;
}
public string getDescription()
{
return description;
}
public void setDescription(string value)
{
description = value;
}
}
In case someone is looking for a short version of getter only (I was):
public class Foo
{
private string bar;
public string Bar => bar;
}

How to implement a class to access objects of several different types in C#?

I'm trying to implement a class to access items of different types, in a similar way to database rows.
However, I have two different ideas in mind, and I don't know which one to choose:
Design 1
public enum ObjectTypeA
{
Undefined,
Integer,
Float
}
public class MyObjectA
{
private object val;
public ObjectTypeA Type
{
get;
private set;
}
public int Integer
{
get
{
if (Type != ObjectTypeA.Integer) throw new Exception();
return (int)val;
}
set
{
Type = ObjectTypeA.Integer;
val = value;
}
}
public float Float
{
get
{
if (Type != ObjectTypeA.Float) throw new Exception();
return (float)val;
}
set
{
Type = ObjectTypeA.Float;
val = value;
}
}
}
Less compile-time checks possible.
Can't use the is operator, GetType(), etc. (reinvents the type system).
Boxing and unboxing for value types.
Can be inherited by other classes (e.g. I can create a "named object" using inheritance).
Design 2
public abstract class MyObjectB
{
}
public class MyIntegerB : MyObjectB
{
public int Value
{
get;
set;
}
public MyIntegerB(int _value)
{
Value = _value;
}
}
public class MyFloatB : MyObjectB
{
public float Value
{
get;
set;
}
public MyFloatB(float _value)
{
Value = _value;
}
}
Shorter and simpler implementation.
Very verbose (casting) to use.
Performance is not critical, but it's still important, since most of the objects that are going to be stored are integers or floats, so boxing overhead matters.
The classes will just contain the values, not methods that depend on the type, etc. so it doesn't matter if the solution uses inheritance.
IMPORTANT: One of the requirements is that there may be two types that use the same underlying type (e.g. two classes derived from MyObjectB may use int as the Value), so using object or generics may not be possible.
Any suggestion about which design to use, or another different design?
EDIT:
The reason I don't like the second one is because it's very verbose to use:
MyObjectB objB = new MyIntegerB(12);
Console.WriteLine(((MyIntegerB)objB).Value);
And because I can't inherit it to create something like a "named object", so I have to attach MyObjectB to the class, and the usage is even more verbose.
I don't see why you wouldn't use generics here. More strongly: I don't see why you need this at all: It seems like Nullable<T> would cover all of your use cases very nicely. If not, implementing this generically is trivial:
public class ValueWrapper<T>
{
public T Value
{
get;
private set;
}
public Type WrappedType
{
get { return typeof(T); }
}
}
public MySpecialInt : ValueWrapper<int>
{
/* etc */
}
why not use generics?
public abstract class MyObjectB<T>
{
public T Value
{
get;
set;
}
public MyObjectB(T _value)
{
Value = _value;
}
}
you only need one class at this point. just instantiate it differently:
var myObj = new MyObjectB<Int>(1);
or
var myObj = new MyObjectB<Float>(0.012);
I know you mentioned not wanting to deal with boxing and unboxing, but I still think a Generic class would be your best bet here.
public class MyObject<T>
{
public MyObject(T t) {
Value = t;
}
public T Value { get; set; }
}
Edit:
One of the requirements is that there
may be two types that use the same
underlying type (e.g. two classes
derived from MyObjectB may use int as
the Value), so using object or
generics may not be possible.
That would only apply if you're extending the class. There's no problem if you wrap the class instead, i.e. create a MyObject<int> and access its Value property, rather than subclassing it.
Having said that, if you want to subclass a generic class, the subclass would also need to be a generic class.
Have you considered generics?
public class MyObjectA<T> {
public T Value {
get; set;
}
}
I've written a similar class that could hold either a single instance of ClassX or an array of ClassX. The trick was that it could change during runtime, so a generic wouldn't suffice, but I still wanted it strong-typed in all cases. It sounds like that's similar to what you're trying to accomplish here.
I chose the first option, and here's why: Wherever possible, I encapsulate complexity within a class to make the class easier to use. Classes should encapsulate away complexity from the caller, making calls to it more concise. If using MyObjectB makes your code more verbose, than I don't think that's the right answer.
if you need heterogeneous collections then this would do.
public enum ObjectTypeA
{
Undefined,
Integer,
Float
}
public class MyObjectA
{
public MyObjectA(object value) : this(value, InfereType(value))
{ }
public MyObjectA(object value, ObjectTypeA type)
{
Value = value;
Type = type;
}
public object Value { get; private set; }
public ObjectTypeA Type
{
get;
private set;
}
public T ValueAs<T>()
{
return (T)Value;
}
}
then use it like
List<MyObjectA> list = GetAllValues();
foreach (var item in list)
{
switch (item.WrappedType)
{
case MyObjecttypeA.Float:
float f = item.ValueAs<float>();
// do something with float
}
}

Categories