Indexers and storage location - c#

one of the restrictions on Indexers is that indexer does not define a storage location, So a value produced by an indexer cannot be passed as a ref or out parameter to a method.
I was wondering the array that we define for indexer isn't a storage location?

I am going to break down each part of your question and try to help you out.
Does Index Define a Location in Storage?
one of the restrictions on Indexers is that indexer does not define a storage location
If saying is "a location somewhere in storage is not guaranteed to be abstractedly defined in the classes implementation of that index" then yes that is correct, abstractly you are defining a value at the Index of the value of your indexer, but that does not guarantee you are accessing a logical location (at an abstract level, at a low level everything has a location). Basically an index is a pretty way to represent a method that takes a value and returns a value a variable(s) that indicates location and using syntax of brackets, and the equal sign to determine which method to call (get or set). I feel like I am getting off topic but you can look up more info on index implementation on on MSDN. But just like methods you have to make it make sense. Here is an example of failing at that making sense and also not having an actual location on the back end of the implementation.
A Weird Example
public class MyClass
{
private void Set(int i,string value)
{
Console.WriteLine("Your Index:{0}\r\nSet Value:{1}",i,value);
}
public string this[int i]
{
get
{
if(i<0)
return "less than zero";
if(i==0)
return "This is zero";
else if(i==1)
return "This is one";
else if(i==2)
return "this is two";
else
return "more than two";
}
set
{
//value is a key word in a setter
//representing the value on you are attempting to set
Set(i,value);
}
}
}
Don't do this
Why you would want to do this I am not sure sure, but if you did want to you could, indexers are just a nice way of expressing a method where it makes sense that it is acting as an index, such as in a Dictionary or a List, and while someone might try to argue that technically the getter in this example does it still makes no sense and shouldn't be using an index to express the method
Can You Pass an Index by ref or out to a Method
So a value produced by an indexer cannot be passed as a ref or out parameter to a method.
since the data you are accessing through the index is encapsulated in the class unless the class exposes a reference to that data you cannot accesses it, therefore you cannot use pass it as a ref or an out parameter in a method call for an indexer property, so we need to see if accessing the indexer exposes a location in memory
Short Answer
No, the key words `ref` and `out` basically tell the IL to make the method take a memory address, `out` requiring the location in memory be assigned a new value, `ref` not requiring a change but still allowing it to happen, since all indexes and properties are not supported in all languages in .NET they are implemented by changing the instructions in "get" and "set" into method calls, `ref` and `out` needs a location in memory of the passed variable, reduced to IL trying to treat a get/set of an indexer as an out variable is equivalent to trying to treat a method or a fresh variable as a `ref` or `out` parameter which is semantically invalid
Long Answer
You cannot, the reason why is because you are calling a method when you use the indexer, say you have this as the method you want to a call
public void CreateNew(out object target)
{
target = new object();
}
What is happening
When you call the CreateNew method at some level instructions:
Take CreateNew Instruction Location
Puts The Location of the variable passed to target into a parameter slot
Changes the value of the memory in the location to a place in the heap
holding the object created by the "new object();" statement
Returns control
It Doesn't work with an indexer
An indexer is called in two cases
Get:
the indexer "Get" method appears where the object is indexed and is trying to be accessed. When this happens a method call is made to some method that represents your get method that has a signature like
ValueType _get_index_IndexType_ValueType( IndexType index)
so if the compiler resolved your call to this as the out parameter then it would be like trying to pass a reference to a variable that hasn't been assigned a location in memory yet. That is why it wouldn't work with the "Get" method and this was done by design as logically you cannot access a location in memory for a variable from the location in memory of an object.
Set:
The indexer "Set" method appears when the object is indexed and on the left hand side of an equal sign, internally it is replace with some method that represents your set method that has a signature like this
void _set_index_IndexType_ValueType(IndexType index, ValueType Value)
So if the call reduces to this it would be the same thing as trying to access the location in memory of a method call, this is not what we want, what we want to do is call the set method when giving a new variable to the index, and get when we are trying to access it. However by design this is not allowed, as you can easily do this on your own...
More Code
If this still doesn't make sense try thinking of the class below, where instead of having an indexer method we just use a Get and Set with an index
public class MyFooIndexableObject
{
/* Note that "ValueType" and "IndexType" are
* just place holders for whatever type you
* decide to make as your return type and
* index type respectively
*
* Using a regular dictionary and an
* extra variable to implement a default
* dictionary so it is not like the example
* is doing nothing.
*/
private Dictionary _internalCollection;
private readonly ValueType _defaultValue = new ValueType();
public void FooSet(IndexType index, ValueType value)
{
if( index == null)
//want to disallow index being null
throw new NullArgumentException("index");
if(_internalCollection==null)
_internalCollection = new Dictionary();
if ( value == null || value == _defaultValue )
// want to remove it
{
_internalCollection.Remove(index);
}
else
_internalCollection[index]=value;
}
/* The Examples FooSet and FooGet
* would be similar method constructs to
* the ones made behind the scenes when
* you define the getter and setter for
* your indexed object
*/
public ValueType FooGet(IndexType index)
{
if( _internalCollection == null
|| !_internalCollection.Contains(index) )
return new _defaultValue;
return _internalCollection[index];
}
public bool TryGetValueAtFirstNonDefault(out IndexType outIndex,
out ValueType outValue)
{
outParam = outIndex = null;
if(_internalCollection!=null)
{
// no need to check we maintain this in the setter and getter
var temp= _internalCollection.FirstOrDefault();
if(temp!=null)
{
outParam = temp.Value;
outIndex = temp.Key;
}
}
return outParam != null;
}
private static void Swap( ref ValueType someRefParam,
ref ValueType otherRefParam)
{
var temp = someRefParam;
someRefParam = otherRefParam;
otherRefParam = temp;
}
//use this instead
public void SwapValueAtIndexes(IndexType index1, IndexType index2)
{
var temp = this.FooGet(index1);
this.FooSet(index1, this.FooGet(index2) );
this.FooSet(index2, temp);
}
public static void Main(string[] args)
{
var indexable = new MyFooIndexableObject();
var index1 = new IndexType(0);
var index2 = new IndexType(1);
ValueType someValue;
//do someValue = indexable[index1]
someValue = indexable.FooGet(index1);
//do indexable[index1] = new ValueType()
indexable.FooSet(index1,new ValueType());
//this does not make sense will not work
//do Swap( out indexable[index1], out indexable[index2] )
//just look how you would try to do this
Swap( ref indexable.FooGet(index1), ref indexable.FooGet(index2));
//Swap is looking for reference to a location in memory
//but the method is returning the value of an object reference
//which you can store in a variable with a location in memory
//but has yet been assigned to one
//Please note the whole idea of "location in memory" is abstract
//it does not technically mean an actual location in physical
//memory but probably an abstraction handled by .NET,
//don't try to hard to make sure you have the technical part
//100% correct, you are significantly detached from the metal
//when coding at this level...the basic idea is the same
//as physical memory locations on a machine
//However, you can accomplish the same things that you would
//want to accomplish with "out" and "ref" by creating methods
//that take the indexed object and an index, such as the
//SwapValueAtIndex method
indexable.SwapValueAtIndex(index1,index2);
//While precisely what SwapValueAtIndex does may
//not translate to what Swap does logically
//it is the same thing, which is good enough for us
}
}
But You Can...
Even though you can't get to the actual reference of the object you can pass the index and the indexed object to a method, this will effectively give you the same effect as a reference to the variable because you can access it using the index and the object that it is located in
public void Swap(MyIndexedObject o, string indexer, object newValue,
ref object oldValue)
{
if(o.Contains(indexer))
{
oldValue = o[indexer];
}
else
oldValue = null;
o[indexer]=newValue;
}
public bool TryGetValue(MyIndexedObject o, string index, out object value)
{
value=null;
if(o.Contains(index))
{
value = o[value];
return true;
}
return false;
}
public void TrySwapValue(MyIndexedObject o, string indexer1, string indexer2)
{
object valHolder1=null,valHolder2=null;
if(TryGetValue(o,indexer1, out valHolder1))
{
Swap(o, indexer2, valHolder1,ref valHolder2);
o[indexer1] = valHolder2;
}
}
What that Means
As you can see you can logically use an index as a location (in a case where the indexed object implementation makes sense) if you have the object, that is where indexed objects make sense to use
Other Options
If you still want a reference to an indexed object you can define a class that has an index and gets and sets the value of the object, in this you could include thing like a history
public class MyObject : Dictionary{}
public class MyPlaceHolder
{
public MyPlaceHolder(string index, MyObject target)
{
Index = index;
TargetObject = target;
}
public string Index {get; private set;}
public MyObject TargetObject {get; private set;}
public object Value
{
get
{
return TargetObject[Index];
}
set
{
var prev = TargetObject[Index];
TargetObject[Index] = value;
_prevVals.Push(prev);
}
}
private Stack _prevVals = new Stack();
public bool UndoSet()
{
if(!_preVals.Count() == 0)
{
Value._prevVals.Pop();
return true;
}
return false;
}
}
Is a Storage Location in Existence for an Index?
I was wondering the array that we define for indexer isn't a storage location?
Yes that array is a location, but the index definition is not a direct reflection of that address. An index into an object is an abstraction of the the concept of an Index, which is something that allows you to access an object based on an index value you pass into it, it does not necessarily do that but it should, technically it could be a method that has nothing to do with a location but it shouldn't.
However the way the object does not expose the actual location underneath is correct, you are using encapsulation to hide the way the location specified by your index method, which is one of the reasons we have object oriented programming I don't care if 0 is a location at the level of the implementation as long as it makes sense when I use it
A Better Example of using an Index
I feel bad for only creating one example of an Indexed object that is actually awful and something hopefully no one ever mistakenly thinks is a good idea, so will show why it makes sense to hide location, this is the purpose behind the abstraction of an index
Let's say I want to make a double key dictionary, I know in some part of my code I am going to implement it, but I don't know how yet, if you have multiple people working so you don't want people to wait around while you code the class, so you can define the interface, and implement it while the other programmers work
public interface IMyDoubleStringDictionaryBase<T>
{
T this[string index1, string value2]
{
get;set;
}
}
The First Implementation
You decide to make it using nested dictionaries, this is what you come up with
public class MyDoubleStringDictionary<T> : IMyDoubleStringDictionaryBase<T>
{
private Dictionary<string,Dictionary<string,T>> _baseCollection;
public T this[string index1, string index2]
{
get
{
if(_baseCollection.ContainsKey(index1))
{
var nextDict = _baseCollection[index1];
if(nextDict.ContainsKey(index2))
{
return nextDict[index2];
}
}
return default(T);
}
set
{
Dictionary<string,T> nextDict;
if(_baseCollection.Contains(index1))
{
nextDict = _baseCollection[index1];
}
else
{
nextDict = new Dictionary<string,T>();
_baseCollection.Add(index1,nextDict);
}
nextDict[index2] = value;
}
}
}
You Have a Problem
For some reason the Dictionary class is not available to you in your production environment, while this might not make sense to you you are told to make one using only the Array data structure, all other abstract data structures you need to define yourself. You decide to make a bucket hash that takes the two hashes of the keys and mixes them
public class MyNewDoubleStringDictionary<T> : IMyDoubleStringDictionaryBase<T>
{
private class Node<T>
{
public Node<T> Next;
public string Key1,Key2;
public T Value;
}
private const int ARRAY_SIZE = 1024;
private Node<T>[] _internalCollection = new Node<T>[ARRAY_SIZE];
private int GetIndex(string key1, string key2)
{
const int key1mask = 0x0F0F0F0F;
const int key2mask = 0xF0F0F0F0;
var key1 = key1mask & key1.GetHashCode();
var key2 = key2mask & key2.GetHashCode();
var result = ((key1 | key2) & 0x7FFFFFFF)% ARRAY_SIZE;
return result;
}
private Node<T> GetOrMakeNode(string key1,string key2)
{
int index = GetIndex(key1,key2);
Node<T> currNode=_internalCollection[index];
if(currNode == null)
{
_internalCollection[index] = currNode = new Node<T>();
}
else
{
while(!(currNode.Key1.Equals(key1)
&&currNode.Key2.Equals(key2))
if(currNode.Next!=null)
{
currNode = currNode.Next;
}
else
{
currNode.Next = new Node<T>();
currNode = currNode.Next;
}
}
if(currNode.Key1 == null || currNode.Key2 == null)
{
currNode.Key1 = key1;
currNode.Key2 = key2;
}
return currNode;
}
public this[string index1, string index2]
{
get
{
var node = GetOrMakeNode(index1,index2);
return node.Value;
}
set
{
var node = GetOrMakeNode(index1,index2);
node.Value = value;
}
}
}
The Result
Even though you had a change in requirements and implementation it did not interrupt any of your team's work, because you aren't making references to internal workings of objects so it would be impossible for it to mess up their work.
Why it Makes Sense
You don't care where the location is, you shouldn't really be worried if the actual implementation is looking at a location just know that you have to interface the index in a certain way and you will be able to use it

http://msdn.microsoft.com/en-us/library/vstudio/6x16t2tx.aspx
Indexer are just special getters and setters. And ref or out are always just local variables. Indexer doesn't even have to point to a storage location but can return computed values.
Indexer don't even have to be used on arrays. For example in a vector image i could define indexers myvectorimage[x][y] such that it returns the color at a x and y location but the data is never stored that way.

Related

C# creating an array in a singelton class

I want to create an array of Disc which id like to include fields string[] Record, int NumberHeads and string extension. so basically grouping them and instantiate the array once and only once as i dont want more than one of this array in the memory. How can i do this as my fields dont seem to be under the array Disc and if i make them public and run the application i get a null reference exception.
I was initially using a struct but I came to realise these cannot be passed from class to class in C#.
class DiscType
{
private static DiscType[] disc;
private static string[];
public bool discSelect;
public int maxRecord;
public int numberHeads;
public string extension;
public static string[] Record
{
get
{
if (record == null)
{
record = new string[1000];
}
return record;
}
}
public static DiscType[] Disc
{
get
{
if (disc == null)
{
disc = new DiscType[10];
}
return disc;
}
}
}
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
for (int i = 0; i < DiscType.Disc.Length; i++)
{
DiscType.Disc[i].Record[i]= "1";
}
}
}
If you want only once instanciation of your array do it like that :
public class Singleton
{
private static Singleton instance;
public string[] MyArray { get; set; }
//better using a List<string>
private Singleton() {
//instanciate MyArray here
}
public static Singleton Instance
{
get
{
if (instance == null)
{
instance = new Singleton();
}
return instance;
}
}
}
After that you just need to call it like that :
Singleton.intance.MyArray
You describe two problems:
After you think you created a DiscType and an array of records, your array of records only contains null values
Your DiscType is not a singleton.
Is Disctype a singleton?
Someone else already described how to create a Singleton, So I wont write this. However I doubt whether DiscType in your design really is a singleton. If you'd describe your design in words, would you talk about the one and only disctype, or would you say: "Although in my designed world it could be that there were several different disctypes, however because of the huge amount of memory and mabye because of the time it takes to create one, it is advised to use only one disctype during the session".
In the latter case, you should not design it as a singleton. The famous gang of four wrote in their book about design patterns (where the singleton is described) as one of the major rules of design:
Design for change
That means, that you should not restrict your design merely for the case that in the current usage it is not needed. If in your current configuration you only need one disctype, just create only one. If in future versions you need two, you don't need to change your disctype.
So careful review your design: are we talking about "the one and only disctype"? or are we only restricting to one because we don't have enough memory?
Why is my array of records empty
To understand this, you need to know the difference between value types and reference types. Simple types and structs are value types. They exist as soon as you declare them. Instances of classes are always reference types: you need to call new ... to create them. If you don't do this, the value is null.
Myclass X;
string text;
int i;
System.Drawing.Point p; // a Point is a struct!
X and text both have a null value, the only thing you can do with them before you assign something to them is compare them with null
i and p already have a value. You can get them and call their methods.
Back to your problem
Your code:
public static string[] Record
{
get
{
if (record == null)
{
record = new string[1000];
}
return record;
}
}
You assign a newly created object to record. the object is an array of strings, which are reference types. You haven't assigned anything to each string, so each string in your array is still null, and you can't do anything with them until you assign something.
The array of strings however is initialized. You can use methods of the array. You can ask for the length of the array. You can also ask for item[3] in which you get the uninitialized (null) string.
List instead of Array
By the way, this method of initializing is a bit unusual. I guess you don't want to reserve memory for records as long as you don't use them. You would have accomplished that by using List.
My advise is to familiarize yourself with class List. It will make your life so much easier. Before long you'll feel the desire to know all collection classes :-)

Jagged dictionary of dynamic depth?

I am trying to extract from a series of strings which represents depth like:
'foo/bar/x'
'foo/bar/baz/x'
'foo/bar/baz/x'
'foo/bar/lol/x'
Where x is a number I don't care about. I've got as far as splitting on the / and looping through, at which point in PHP I'd do something like check where in the loop I am (using for (i=0; etc)) and then use that to determine my depth to build an output array like:
output['foo']['bar'] = 1
output['foo']['bar']['baz'] = 2
output['foo']['bar']['lol'] = 1
The trouble is the 'depth' is dynamic and might be either just 3/4 deep (which I could just account for with lots of checks on the value of i and handling them separately) or say 10 or more deep in which case some kind of recursive function is probably best.
I've come across the issue that to have a string as an array index I need to use a dictionary, but you have to specify the types in the dictionary, meaning you need to know the depth in advanced (correct me if I'm wrong) when instantiating a dictionary object.
I guess an attack might be something like calling a recursive function such that each time it's called you pass i to indicate the depth, then the function calls itself decrementing i each time until it has built the portion of the tree from that input string but it's what storage structures I use for that in C# that I am not sure about.
The final output will be a CSV that I can open as a spreadsheet to look like:
Foo 0
|__Bar 1
|__Baz 2
|__Lol 1
Perhaps one direction for a solution is to use a pure C# Array and simply store the title (e.g. foo) in there, keeping information out of array indicies, which is probably best practice anyway. Thanks.
You can create your own class with following members:
class Directory
{
public int Value { get; set; }
public Dictionary<string, Directory> SubDirectories { get; set; }
}
Store your data using it and then recursively export it to CSV.
To get output["foo"]["bar"] syntax possible implement indexer within your class:
public Directory this[string name]
{
get { return SubDirectories.ContainsKey("name") ? SubDirectories[key] : null; }
set { SubDirectories.Add(name, value); }
}
While Marcin Juraszek solution is great, I just want to expand his answer just a little bit with dynamic sugar. It's not the fact, that this solution will fit your need, but just consider it as an example. I will make Directory<T> generic, so you can use whatever type for value (note that due to dynamic nature I have one cast in implementation (T)value)
class Directory<T> : DynamicObject
{
private T Value;
private Dictionary<string, Directory<T>> SubDirectories;
public Directory()
{
SubDirectories = new Dictionary<string, Directory<T>>();
}
public override bool TryGetMember(GetMemberBinder binder, out Object result)
{
if (!SubDirectories.ContainsKey(binder.Name))
SubDirectories[binder.Name] = new Directory<T>();
result = SubDirectories[binder.Name];
return true;
}
public override bool TrySetMember(SetMemberBinder binder, Object value)
{
if (!SubDirectories.ContainsKey(binder.Name))
SubDirectories[binder.Name] = new Directory<T>();
SubDirectories[binder.Name].Value = (T)value;
return true;
}
public override string ToString()
{
return Value.ToString();
}
}
And now you can use dynamic feature, available from C# 4.0
dynamic dir = new Directory<string>();
dir.foo = "Foo Value";
dir.foo.bar = "Bar Value";
dir.foo.bar.baz = "baz value";
dir.foo.bar.Lol = "Lol value";
Console.WriteLine(dir.foo.bar.Lol); //will print Lol value
Console.WriteLine(dir.foo.bar.baz); //will print baz value
which is:
Foo Foo Value
|__Bar Bar Value
|__Baz baz value
|__Lol Lol value
you can also override TryGetIndex and TrySetIndex so that you can pass complex strings, which can't be used as properties in C#

How to have a C# readonly feature but not limited to constructor?

The C# "readonly" keyword is a modifier that when a field declaration includes it, assignments to the fields introduced by the declaration can only occur as part of the declaration or in a constructor in the same class.
Now suppose I do want this "assign value once" constraint, but I would rather allow the assignment be done outside of constructors, a lazy/late evaluation/initialization maybe.
How could I do that? and is it possible to do it in a nice way, for example, is it possible to write some attribute to describe this?
If I understand your question correctly, it sounds like you just want to set a field's value once (the first time), and not allow it to be set after that. If that is so, then all the previous posts about using Lazy (and related) may be useful. But if you don't want to use those suggestions, perhaps you can do something like this:
public class SetOnce<T>
{
private T mySetOnceField;
private bool isSet;
// used to determine if the value for
// this SetOnce object has already been set.
public bool IsSet
{
get { return isSet; }
}
// return true if this is the initial set,
// return false if this is after the initial set.
// alternatively, you could make it be a void method
// which would throw an exception upon any invocation after the first.
public bool SetValue(T value)
{
// or you can make thread-safe with a lock..
if (IsSet)
{
return false; // or throw exception.
}
else
{
mySetOnceField = value;
return isSet = true;
}
}
public T GetValue()
{
// returns default value of T if not set.
// Or, check if not IsSet, throw exception.
return mySetOnceField;
}
} // end SetOnce
public class MyClass
{
private SetOnce<int> myReadonlyField = new SetOnce<int>();
public void DoSomething(int number)
{
// say this is where u want to FIRST set ur 'field'...
// u could check if it's been set before by it's return value (or catching the exception).
if (myReadOnlyField.SetValue(number))
{
// we just now initialized it for the first time...
// u could use the value: int myNumber = myReadOnlyField.GetValue();
}
else
{
// field has already been set before...
}
} // end DoSomething
} // end MyClass
Now suppose I do want this "assign value once" constraint, but I would rather allow the assignment be done outside of constructors
Note that lazy initialization is complicated, so for all of these answers you should be careful if you have multiple threads trying to access your object.
If you want to do this inside the class
You can use the C# 4.0 built-in lazy initialization features:
http://msdn.microsoft.com/en-us/library/dd997286.aspx
http://msdn.microsoft.com/en-us/library/dd642331.aspx
http://sankarsan.wordpress.com/2009/10/04/laziness-in-c-4-0-lazyt/
Or for older versions of C#, just supply a get method, and check if you're already initialized by using a backing field:
public string SomeValue
{
get
{
// Note: Not thread safe...
if(someValue == null)
{
someValue = InitializeSomeValue(); // Todo: Implement
}
return someValue;
}
}
If you want to do this outside the class
You want Popsicle Immutability:
http://blogs.msdn.com/b/ericlippert/archive/2007/11/13/immutability-in-c-part-one-kinds-of-immutability.aspx
http://msdn.microsoft.com/en-us/library/ms750509.aspx
http://csharpindepth.com/Talks.aspx (search for "popsicle immutability" and you'll find a video)
Basically:
You make the whole class writable, but add a Freeze method.
Once this freeze method is called, if users try to call setters or mutator methods on your class, you throw a ModifyFrozenObjectException.
You probably want a way for external classes to determine if your class IsFrozen.
BTW, I made up these names just now. My selections are admittedly poor, but there is no generically followed convention for this yet.
For now I'd recommend you create an IFreezable interface, and possibly related exceptions, so you don't have to depend on the WPF implementation. Something like:
public interface IFreezable
{
void Freeze();
bool IsFrozen { get; }
}
You can use the Lazy<T> class:
private readonly Lazy<Foo> _foo = new Lazy<Foo>(GetFoo);
public Foo Foo
{
get { return _foo.Value; }
}
private static Foo GetFoo()
{
// somehow create a Foo...
}
GetFoo will only be called the first time you call the Foo property.
This is know as the "once" feature in Eiffel. It is a major oversight in C#. The new Lazy type is a poor substitute since it is not interchangeable with its non-lazy version but instead requires you to access the contained value through its Value property. Consequently, I rarely use it. Noise is one of the biggest problems with C# code. Ideally, one wants something like this...
public once Type PropertyName { get { /* generate and return value */ } }
as oppose to the current best practice...
Type _PropertyName; //where type is a class or nullable structure
public Type PropertyName
{
get
{
if (_PropertyName == null)
_PropertyName = /* generate and return value */
return _PropertyName
}
}

Object pointers(object*) in C#

What I want to do is, I want to pass a pointer to a function that may be any type of a variable(int, long, string, even a class I mean I should be able to pass any variable's pointer). I'm doing this like that
unsafe class whatever
{
whatever(object* variable)
{
this.variable = variable;
}
}
ERROR IS: Cannot take the address of, get the size of, or declare a pointer to a managed type ('object')
Why I want to do is, I will store the variables passed through the constructor and will use their ToString() method, I'm trying to make a class that is for console applications, Refreshing the variables with their updated variables.
If I could do it like that My code will look like that
unsafe class whatever
{
whatever(object* variable)
{
this.variable = variable;
}
object* variable;
public override string ToString()
{
return *variable.ToString();
}
}
Maybe you should pass in a delegate that your class can use to obtain the “object string”.
class MyFancyClass
{
Func<string> getObjectString;
public MyFancyClass(Func<string> getObjectString)
{
this.getObjectString = getObjectString;
}
private MyOtherThread()
{
// ...
string desc = getObjectString();
// ...
}
}
// ...
long value = 34;
MyFancyClass fancy = new MyFancyClass(() => value.ToString());
// ...
value = 88;
// getObjectString() should now reflect the new value.
// The variable is captured in the lambdas closure.
Be careful though, because the delegate is called from another thread and simply calling ToString() may not be safe for all objects and require locking. However a delegate allows the caller to do this, depending on the object.
Pointers will get ugly, require unsafe code and aren't stable. The garbage collector can move objects around freely, if you don't explicitly make the pointers fixed. References can't be stored and you can only pass them around.
In C#, you usually don't use pointers. If you want to refer to a storage location, try this:
whatever(ref object variable)
{
}
Else, i would rather recommend using a wrapper class or another way to get to some variable.
A wrapper might look like this:
class Wrapper
{
public object Value { get; set; }
}
If you want to get the address of a variable it can't be a complex managed type. However, you can do something like this (assuming an unsafe context):
int a = 1;
IntPtr addr = ( IntPtr )( &a );
( * ( int* ) addr ) = 4;
a = 4;
Is this what you're looking for?
Edit:
If you're just wanting to save a "function pointer" from the object, just use a delegate to hold that.
class whatever
{
public whatever(object variable)
{
getVariableValue = variable.ToString;
}
Func<string> getVariableValue;
public override string ToString()
{
return getVariableValue();
}
}
void Main()
{
var type = new { F1 = "test", F2 = "value" };
whatever w = new whatever( type );
Console.WriteLine( w ); // This will invoke ToString
}
Output: { F1 = test, F2 = value }
You want a void* but becareful with those. if you make the wrong cast it will crash. it might be a wise idea to make a struct and cast to an intptr in this case.

Should I use a Field or Property within the class to set values

So I got into a friendly argument with a co-worker over a piece of code:
public sealed class NewObject
{
private string _stuff = string.Empty;
public string Stuff
{
get { return GetAllStuff(); }
}
private string GetAllStuff()
{
//Heavy string manipulation of _stuff
}
public NewObject(string stuffToStartWith)
{
_stuff = stuffToStartWith;
}
public static NewObject operator +(NewObject obj1, NewObject obj2)
{
if (obj1 == null)
throw new ArgumentNullException();
if (obj2 == null)
throw new ArgumentNullException();
NewObject result = new NewObject(string.Empty);
result._stuff = String.Concat(obj1._stuff, obj2._stuff);
return result;
}
}
The argument was over the operator override. My co-worker feels that it's not best programming practice to set values of private fields anywhere but the constructor. The solution proposed by my co-worker was to refactor the name of the Stuff property to AllStuff and add a property, Stuff, that has a get AND set accessor and use the new Stuff property in the operator override. Making it look like this:
public static NewObject operator +(NewObject obj1, NewObject obj2)
{
if (obj1 == null)
throw new ArgumentNullException();
if (obj2 == null)
throw new ArgumentNullException();
NewObject result = new NewObject(string.Empty);
result.Stuff = String.Concat(obj1.Stuff, obj2.Stuff);
return result;
}
I disagree. I feel the first way is better since it keeps the property read-only outside the class. My question is, which way is the best practice for object-oriented design?
You could give yourself a private set on the property (which would retain visibility or lack thereof while allowing you to use property syntax), but that doesn't really address the point.
Within the class, I say that variables are fair game. Anywhere outside, including inherited classes, should get and set the property, but within the declaring class I say it's OK to assign the private member.
The general issue has to do with a contract policy.
The notion of a (public set) property is that when it is called, other actions may be taken in addition to the semantic notion of changing state. For example, calling a setter may fire events, trigger a peripheral device and so on.
Your coworker is saying that by not using the property, you're side-stepping the contract and no events will be fired.
So here's you should do from your coworker's point of view:
this.Prop = CalculateSomeValue();
if (this.Prop < kPropMin) {
this.Prop = kPropMin;
}
else if (this.Prop > kPropMax * 2) {
this.Prop = kPropMax * 2;
}
this.Prop = this.Prop / 2;
Now, this is a contrived case, but I've just hit a possible heavyweight property up to three times in the get and up to three times in the set, and one of those might be illegal (setting to kHighLimit / 2). I can work around this by using a local and calling the set precisely once at the end. I'd rather just mess with the field, though.
I think a better approach is to take it pragmatically: use the property inside your class if and only if you want to invoke all the side-effects of a set or a get, otherwise obey the spirit of the property instead.
-- clarification --
By obey the spirit of the property, let's say that my set property looks like this:
bool PropValueOutOfRange(int val) {
return val < kPropMin || val > kPropMax;
}
public int Prop {
set {
if (PropValueOutOfRange(value))
throw new ArgumentOutOfRangeException("value");
if (PropValueConflictsWithInternalState(value))
throw new ArgumentException("value");
_prop = value;
NotifyPeriperalOfPropChange(_prop);
FirePropChangedEvent(/* whatever args might be needed */);
}
}
In this I've factored out a lot of the grungy details, but that lets me reuse them. So now I feel confident in touching the private field _prop because I have the same infrastructure for making sure that I keep it in range and to notify the peripheral and fire the event.
This lets me write this code:
_prop = CalculateSomeValue();
if (_prop < kPropMin)
_prop = kPropMin;
else if (_prop > kPropMax * 2)
_prop = kPropMax;
_prop /= 2;
NotifyPeripheralOfPropChange();
FirePropChangedEvent();
I'm using the same tools as those used to build the property so I'm working within the spirit of the property. I maintain correct range (but don't throw - I know better, I'm the implementer), hit the peripheral and fire events, and I do it thoughtfully, readably, and efficiently - not indiscriminately.
You're right
err... to elaborate, your private variables are yours to do as you please. If someone does an operation on you that changes the value of the object, (especially something like +), theres nothing wrong with modifying the value outside of the constructor. Thats the whole point of them being private.
Unless you want it immutable...
Update
The more i think about it, the more I believe your co-worker is confusing 'private' variables with 'constant' ones - or perhaps merging the two concepts. There is no reason that private variables have to remain the same throughout the life of the object, which is what your friend seems to be implying. const is for unchanging, private is for the object only, they are two very distinct patterns.
Update2
Also, his design falls apart if suddenly your object has more than just a string - and the variables are intertwined (think of a string object, that has a char* and a len, and must be maintained together). The last thing you want is for the user to have to deal with internal variables of an object. Let the object be an object and maintain its own internal values and present a single entity to the user.
I don't see what the benefit of his approach would be.
I personaly prefer to have no fields at all, hence I use auto-implemented private properties instead of private fields and public-get private-set properties if want to have public read-only properties.
If I have to add code to the property, I still only use the field inside of the property accessors and use the getters and setters everywhere else including the constructor.
I have to use fields, too, if I need readonly fields, but C# 4.0 will introduce read-only properties.
Further I would have avoided the whole problem by using the following code.
public static NewObject operator +(NewObject obj1, NewObject obj2)
{
return new NewObject(String.Concat(obj1.Stuff, obj2.Stuff));
}
My prefered implementation would be something like this.
public sealed class NewObject
{
private String Stuff { get; set; }
// Use a method instead of a property because the operation is heavy.
public String GetAllStuff()
{
// Heavy string manipulation of this.Stuff.
return this.Stuff;
}
// Or lets use a property because this.GetAllStuff() is not to heavy.
public String AllStuff
{
get { return this.GetAllStuff(); }
}
public NewObject(String stuffToStartWith)
{
this.Stuff = stuffToStartWith;
}
public static NewObject operator +(NewObject obj1, NewObject obj2)
{
// Error handling goes here.
return new NewObject(String.Concat(obj1.Stuff, obj2.Stuff);
}
}

Categories

Resources