Get instance name c# - c#

Maybe, this question is stupid, but in my specific situation i want to get instance name, so what i mean :
class Student
{
private string name {get; private set;}
public Student(string name)
{
this.name = name
}
public getInstanceName()
{
//some function
}
}
so when i make an student
Student myStudent = new Student("John");
it's stupid but i want this
myStudent.getInstanceName(); // it should return 'myStudent'

This is now possible in C# 6.0:
Student myStudent = new Student("John");
var name = nameof(myStudent); // Returns "myStudent"
This is useful for Code Contracts and error logging as it means that if you use "myStudent" in your error message and later decide to rename "myStudent", you will be forced by the compiler to change the name in the message as well rather than possibly forgetting it.

This is not possible in C#. At runtime, the variable names will not even exist, as the JIT removes the symbol information.
In addition, the variable is a reference to the class instance - multiple variables can reference the same instance, and an instance can be referenced by variables of differing names throughout its lifetime.

This question is very old, but the answer changed with the release of .Net Framework 4.6. There is now a nameof(..) operator which can be used to get the string value of the name of variables at compile time.
So for the original question C# nameof(myStudent) // returns "myStudent"

Give this a try
string result = Check(() => myStudent);
static string Check<T>(Expression<Func<T>> expr)
{
var body = ((MemberExpression)expr.Body);
return body.Member.Name;
}
Or
GetName(new { myStudent });
static string GetName<T>(T item) where T : class
{
return typeof(T).GetProperties()[0].Name;
}

Variable names exist only for your benefit while coding. Once the the code is compiled, the name myStudent no longer exists. You can track instance names in a Dictionary, like this:
var students = new Dictionary<string, Student>();
var students["myStudent"] = new Student("John");
// Find key of first student named John
var key = students.First(x => x.Value.Name == "John").Key; // "myStudent"

No, but you could do this
var myStudent = new Student("John").Named("myStudent");
var nameOfInstance = myStudent.Name();
public static class ObjectExtensions
{
private static Dictionary<object,string> namedInstances = new Dictionary<object, string>();
public static T Named<T>(this T obj, string named)
{
if (namedInstances.ContainsKey(obj)) namedInstances[obj] = named;
else namedInstances.Add(obj, named);
return obj;
}
public static string Name<T>(this T obj)
{
if (namedInstances.ContainsKey(obj)) return namedInstances[obj];
return obj.GetType().Name;
}
}

So I've been searching around for about a week trying to figure out how to do this. While gathering bits and pieces of stuff I didn't know I found a relatively simple solution.
I think the original poster was looking for something like this, because if you have to use the name of the class to find out the name of the class then what's the point..
For those saying "It's not possible" and "Why would you want to.." my particular reason is for a class library where I have a class that the app developer can call the instances whatever they want, and it's meant to have multiple instances with different names. So I needed a way to be able to identify those instances so I can use the right one for the circumstance.
public static List<Packet> Packets = new List<Packet>();
public class Packet
{
public Packet(string Name)
{
Packets.Add(this);
name = Name;
}
internal string _name;
public string name
{
get { return _name; }
set { _name = value; }
}
}
It does require that they pass in the name of the instance as I've not yet figured out how to acquire the name they're using from inside the constructor. That is likely the thing that isn't possible.
public Packet MyPacket = new Packet("MyPacket");
This creates the instance, stores a reference to it in Packets and saves it's name in the newly created instance.
To get the name associated with the Packet and connect it to a variable..
Packet NewName = Packets[Packets.FindIndex(x => x.name == "MyPacket");
Whether you use the same variable name or a new one doesn't really matter, it's just linking the instance you want to it.
Console.WriteLine(NewName.name); // Prints MyPacket
For instances with the same name you would have to come up with some other way to tell them apart, which would require another list and some logic to determine which one you want.

No, this is not possible, because it's totally ridiculous. An object can never, in any way, know the name of the variable you happen to assign it to. Imagine:
Student myStudent = new Student("John");
Student anotherStudent = myStudent;
Console.Write(anotherStudent.getInstanceName());
Should it say myStudent or anotherStudent? Obviously, it has no clue. Or funnier situations:
School mySchool = new School("Harvard");
mySchool.enroll(new Student("John"));
Console.Write(mySchool.students[0].getInstanceName());
I really would like to know what this would print out.

Related

How to create a "pointer-like" class, easily exposing functions of member?

What I am trying to do is find the most elegant way to create a "pointer-like" class for a specific object/class type that I have in a project.
What I mean is a little confusing without an example. Take this really simple class:
public class MyClass
{
private string _name;
public string GetName() { return _name; }
public void SetName(string name) { _name = name; }
}
I want to create a second class which is like a pointer to it like this:
public class MyClassPtr
{
private MyClass _obj;
public bool IsValid = false;
public MyClassPtr(MyClass obj) { _obj = obj; IsValid = true; }
public void InvalidatePtr()
{
IsValid = false;
obj = null;
}
// SOME MAGIC HERE?
}
The challenge: The key is that I want to elegantly have MyClassPtr provide an interface to all of the public methods/members in MyClass without writing wrappers and/or accessors around each method/member.
I know that I could do this:
public class MyClassPtr
{
public string GetName() { return _obj.GetName(); }
...
}
But that's what I want to avoid. Is there some fundamental abstraction that I don't know of that I can apply to MyClassPtr to allow it to easily re-expose the methods/members in MyClass directed through _obj? I do NOT want MyClassPtr to inherit MyClass. Should MyClassPtr be a type instead, and some trick with accessors to expose the methods/members of MyClass?
Edit: More context on why I am looking for such a design through an example. Here is the overall goal. Imagine a platform that parses through data about people and when it finds information about a person, it creates an instance of Person with that information. You could get a handle to that person like:
Person person1 = platform.GetPerson(based_on_data);
Now, imagine the platform had two instances of Person that it thought were different people, but all of a sudden information came in that strongly suggested those two instances actually refer to the same person. So, the platform wants to merge the instances together in to a new object, let's call it personX.
Now, floating around in the platform someone had a copy of one of those two instances that got merged, which was person1. What I want to do is on-the-fly replace person1 with personX. Literally, I want person1==personX to be true, NOT just that they are two different objects with the same data. This is important since the platform could make a change to personX and unless the two objects are literally equal, a change to personX would not be automatically reflected in person1.
Since I can't on-the-fly replace person1 with personX I had that idea that I wouldn't give direct access to Person, instead I would give access to PersonPtr which the platform (on-the-fly) can change what Person it is pointing to. This would insurance that once person1ptr gets updated to point to personX, if a change is made in personX it will be seen in person1ptr
You could of course use something like
public class MyClassWrapper
{
MyClass _obj;
public MyClassWrapper(MyClass obj)
{
_obj = obj;
}
public void Invoke(Action<MyClass> action)
{
action(_obj);
}
public U Invoke<U>(Func<MyClass, U> func)
{
return func(_obj);
}
public void ChangeTo(MyClass obj)
{
_obj = obj;
}
}
Given your class looks like
public class MyClass
{
public string Name { get; set; }
}
Example:
var person1 = new MyClass { Name = "Instance1" };
var person2 = new MyClass { Name = "Instance2" };
var wrapper = new MyClassWrapper(person1);
wrapper.Invoke(x => x.Name += "original");
var x = wrapper.Invoke(x => x.Name); // Instance1original
wrapper.ChangeTo(person2);
var y = wrapper.Invoke(x => x.Name); // Instance2
but it has a major drawback: you can't access members directly, so you can't bind the data (to a DataTable or a Control).
It would be better to implement all members of your class also in your wrapper class. If you're afraid changes in your class will be forgotten to be implemented in your wrapper, just use an interface:
public interface IMyClass
{
string Name { get; set; }
}
public class MyClass : IMyClass
{
public string Name { get; set; }
}
public class MyClassWrapper: IMyClass
{
MyClass _obj;
public MyClassWrapper(MyClass obj)
{
_obj = obj;
}
public string Name
{
get { return _obj.Name; }
set { _obj.Name = value; }
}
}
Note that regardless which approach you use, you'll have to always keep a reference to the wrapper instance to actually change the underlying instance (using something like static aside).
Also, changing the underlying instance of such a wrapper without telling the component using it that it changed don't seem to be a good idea. Maybe your system is simple enough to get away with a wrapper; that's something you have to decide for yourself.
Maybe your wrapper should simply have an Invalid flag (and/or use an event to signal a change of the underlying object.). Once the underlying object is merged, it is set to true and each member access should throw an exception. This would force the component using the wrapper to deliberately react to changes and to reload the data from your service.
All in all, I think using such a wrapper will just clutter up your code and be error prone (just imagine adding multithreading to the mix). Think twice if you really need this wrapper.
Why not just simply ask your service for a new instance of your class everytime you use it (the service can simply use a cache)? Sure, you can't prevent that someone somewhere keeps a reference; but at least you'll keep your sanity.

"Writable" reference to object

Not sure I'm able to formulate this question in a way someone would simply understand, so lets have a cool marketing example:
public class Part
{
public MemberType member;
...
}
public class Product
{
public Part part1;
...
}
...
Product product = new Product();
I need to modify the public product's part1. So, the natural method is to write something like:
product.part1 = new Part();
Now, an algorithm (let's say a sort of search one) would go through the product object and identify the part1 as an interesting part and returns reference to it:
Part Search(Product product)
{
Part part = null;
...
part = product.part1;
...
return part;
}
...
interesting_part = Search(product);
We can alter the product object via the interesting_part like
interesting_part.member = whatever;
Now, the question: in c/c++ if the Product.part1 is pointer to Part and Search returns address of this pointer, we could replace the part1 just by assigning new value to this address. AFAIK this is not possible for c# reference:
interesting_part = new Part();
Just creates new object and copies its reference to the interresting_part, but without knowing the member parent (product object), we are not able to modify the (product.part1) reference, just its content. We would need second level of the reference.
Is there something like "ref reference" type which would accept reference addresses? In such hypothetical case the search would return ref Part and assigning to such value would replace the referenced object with the new one.
Thanks.
You could create a Reference class
class Reference<T>
{
private Func<T> m_Getter;
private Action<T> m_Setter;
public Reference(Func<T> getter, Action<T> setter)
{
m_Getter = getter;
m_Setter = setter;
}
public T Value
{
get{return m_Getter();}
set{m_Setter(value);}
}
}
Now you can say
Reference<Part> Search(Product product)
{
Part part = null;
...
part = product.part1;
var reference=new Reference<Part>(()=>product.part, (value)=>product.part1=value);
return refernce;
}
var partReference = Search(product);
partReference.Value = someNewPart;
In a very similar situation, I keep a reference of the parent in each child object. Simple and works.
public class Part
{
public MemberType member;
...
public Product parent;
Part(Product p)
{
parent = p;
}
}
public class Product
{
public Part part1;
...
}
I don't think you can do that. You would need to mutate a reference to you product object, or have some other added layer of reference.
So you need to build a Proxy object. The Product would get a reference to the Proxy and the (hidden) Part can be exchanged. This is a common OO design pattern. Of course the Proxy can delegate method calls to the Part.
If you want to change the field, you can do this,
class Program
{
static void Main(string[] args)
{
var holder = new Holder();
holder.CurrentPart = new Part() { Name = "Inital Part" };
Console.WriteLine(holder.CurrentPart.Name);
TestRef(ref holder.CurrentPart);
Console.WriteLine(holder.CurrentPart.Name);
Console.ReadKey();
}
public static void TestRef(ref Part part)
{
part = new Part() { Name = "changed" };
}
}
public class Part
{
public string Name;
}
public class Holder
{
public Part CurrentPart;
}
This won't work with property, indexers and so.
As far as I know, there isn't any way to alter an object's "parent" without having a reference to it. So I believe the official answer to your question as written is "no".
That said, there are many ways to accomplish the task as written. The easiest option is to add a reference to the parent from the part object. You end up with something like:
public class Part
{
public Product parentProduct;
public MemberType member;
...
}
Now whenever you have a part object you also know what product the part goes with (IF it does indeed go with a part at all). This is not necessarily a bad coding style but there certainly are pitfalls. You can update the product, but forget to update the parts in that product, you are coding so that parts have one product, but what if that part has many products? You can see how this works, but it can get complicated.
Taking this and making it more generic you can have reference the parent as an object type. That looks like:
public class Part
{
public object parent;
public MemberType member;
...
}
Now when you want to use the parent you can write something like:
var parentProduct = myPart.parent as Product;
This will convert the parent to a product or will assign null if the parent is not of the type Product. Now parts can have parents of any given type you would want and you have made the pattern more flexible.
One final pattern I know people use frequently is delegates. This allows you to pass in a function effectively modifying the way "search" is working. Say what you really want to do is search, then process the results in some manner, but you want that processing to be flexible (this may be what you were doing with the results). In that case, you can use delegates as follows:
// define the delegate
public delegate void ProcessResultDelegate(Product result, Part interestingPart);
// an example search function
public static void RunSearch(IEnumerable<Product> products, ProcessResultDelegate processingHelper)
{
// run the search... then call the processing function
processingHelper(searchResult, interestingPart);
}
This pattern is more useful when you want to modify the behavior of a routine rather than the return value from that routine.
Anyways, hope these patterns help some!

Why are my values not being kept between instances of a type?

I have the class:
public class pro {
private string url = string.Empty;
public string GetURL() { return url; }
public void SetURL(string value) { url = value; }
}
In this line I'm getting value:
string url = li1.Value;
pro itm = new pro(); // I have create Proprtie so I'm calling that
itm.SetURL(url); // here I'm setting value
Then later:
pro itm = new pro(); //properties object I have created
string url = itm.GetURL(); // I'm not getting value which I have set in first
class.
I have create Proprties also; what am I doing wrong?
May be I understood your problem :
The thing is that in second you create a new instance of pro class. If you want to acess the string value set in first class, you should use that first pro object.
If it's not your problem, please clarify.
Every class instance (i.e. every new pro()) has different instance values; it is perfectly expected that if you have 2 different instances, then they will not share a URL, for example. If you want to share this, you should make the same pro instance available to both places, by passing the pro around.
Incidentally, GetURL() / SetURL() is not idiomatic C# - it would be more common to have a property, i.e.
public string Url {get;set;}
which you would then access as:
YourType item = new YourType();
item.Url = "http://foo.com/bar/";
// ...
string url = item.Url;
From the comments, it sounds like you are talking about static data; I should emphasise that using static for this is not usually a good idea, and can lead to lots of problems with testing, multi-tenancy, threading, etc; but: the following works without any instances:
public class Properties {
public static string Url {get;set;}
}
...
Properties.Url = "http://foo.com/bar/";
...
string url = Properties.Url;
note: no instances at all.
However, it is almost always preferable to simply keep an instance available, and use instance properties against that common instance.
If you need to have some class like application properties you can use static class.
public static class pro
{
public static string Url {get; set;}
}
and use it like pro.Url = "aa";

How can I avoid ref parameters?

I have a method that has 2 ref parameters:
public void ReplaceSomething(ref int code, ref string name)
{
...
}
I want to avoid this, as it is not a good design (and scales poorly). What are my options?
I've though about using an anonymous object, but that doesn't seem like a good idea, either.
Object something = new { code = 1, name = "test" };
ReplaceSomething(something);
Are the code and the name closely linked together? If so, consider creating a type to put the two of them together. Then you can return a value of that type.
Alternatively, you might consider returning a Tuple<int, string>.
(In both cases you can accept an input parameter of the same type, of course. As you haven't shown any of your code, it's not really clear whether you use the existing values of the parameters, or whether they could basically be out parameters.)
Why don't you want to use ref arguments? That seems like a perfectly good way to change some caller values.
The other approach would be to implement a return value. Maybe you need to better explain what the problem is?
If these values are tightly coupled and "belong together" you could define a custom class that holds your properties and either return a new instance (assuming its immutable) of that or update its properties:
class Code
{
public int Value {get;set;}
public string Name {get;set;}
}
public Code UpdateCode(Code code)
{
...
}
If you need to return these values, you can either use a tuple
public Tuple<int, string> ReplaceSomething(int code, string name)
{
...
}
Or create your own class-wrapper that holds the values as properties
public Foo ReplaceSomething(int code, string name)
{
var foo = new Foo(){...};
return foo;
}
class Foo
{
public int IntValue{get;set;}
public string StringValue{get;set;}
}
Why would you change it? ref parameters make sense at times, and if this is one of those times - use them. You could introduce a new class that contains that pair of values, which only makes sense if those values come together often.
I say, keep it.
Based on your question, I could be way off. What do you mean by replacing ref? Are you looking to overload?
public void ReplaceSomething(int code, string name)
{
// ...
}
public void ReplaceSomething()
{
return ReplaceSomething(1, "test");
}
Edit:
ok, so you need to return the code and the name what are the calculations that need to be made? Jon Skeet's answer about a tuple could be right, or you might need a POCO that contains the code the name and the replaced
public void ReplaceSomething(int code, string name)
{
var replaced = new Replaced();
replaced.code = code;
replaced.name = name;
var r;
// do some replacement calculations
replaced.replaced = r;
return replaced;
}
public class Replaced {
public string name {get; set;}
public int code {get; set;}
public string replaced {get; set;}
}

Using static objects

My understanding is any method which does not modify state of the constaining class is a prime candidate to be made static because it does not touch the instance. An instance would be that containing class's data (fields/properties) so if I had a person class with a property called Name (and just that one property), and I am not modifying that property then my class can be set as static, but of course, but the function could be working with another object. Is this the right thing to look for when checking if a method should be made static?
Static variables are described as global variables, but what is the difference of this to any publicly variable? All the variables are in the server's memory and will be lost in a reboot etc. And then use this variable to hold expensive-to-get data (eg running stored procedures in a loop etc).
Thanks
My understanding is any method which does not modify state of the constaining class is a prime candidate to be made static because it does not touch the instance.
I wouldn't say it's a prime candidate, but rather just a candidate. Personally, I think methods should be made static if the API would suggest that it should be static from a logical, algorithmic standpoint. Technically, any method which doesn't change state can be static, but I don't believe it necessarily should be static.
and I am not modifying that property then my class can be set as static, but of course, but the function could be working with another object.
You can only set your class as static in C# if it has absolutely no instance variables. "Instances" of a static class don't exist (and cannot exist), nor can non-static members.
Now - for what I think you're really after...
The difference between a static variable and a non-static variable has to do with how it's accessed. When you define a static field on a class, you're defining a field that will always have a single instance (instance of the field) tied to the class itself. When you define a non-static, normal field, on the other hand, you will potentially have many instances of your field, each residing within one instance of your class.
This is why static variables are often described as global - anything that has access to the class has access to it's one copy of the static variable (provided its publicly accessible). However, non-static fields are different - you need to have a reference to the specific instance of the class in order to read or write to a non-static member.
.
My understanding is any method which
does not modify state of the
constaining [sic] class is a prime candidate
to be made static because it does not
touch the instance.
I don't think this is the right way to think of static vs. non-static. Rather, any method which is not related to the state of a class instance can be static. A name is obviously associated with a particular person, so a Name field on a Person class should almost certainly not be static. Otherwise, you could end up with a scenario like this:
public class Person {
public static string Name { get; set; }
public Person(string name) { Name = name; }
public override string ToString() {
return Name;
}
}
Person dan = new Person("Dan";
Person john = new Person("John";
// outputs "John"
Console.WriteLine(john);
// outputs "John" again, since Dan doesn't have a name property all his own
// (and neither does John, for that matter)
Console.WriteLine(dan);
EDIT: Now, suppose we have a property such as House which can belong to not one but several people. blade asks: "How would this be modeled in code - static?"
My answer: NO, for the same reason already mentioned above. Suppose I've fixed the problem above by making the Name property non-static. Then I introduce a new static House property. Now I have a situation like this:
public class Person {
public string Name { get; set; }
public static House House { get; set; }
public Person(string name, House house) {
Name = name;
House = house;
}
public override string ToString() {
return String.Concat(Name, ", ", House);
}
}
public class House {
public double SquareFootage { get; set; }
public House(double sqft) { SquareFootage = sqft; }
public override string ToString() {
return String.Format("House - {0} sq. ft.", SquareFootage);
}
}
House danAndKatsHouse = new House(1000.0);
House johnsHouse = new House(2000.0);
Person dan = new Person("Dan", danAndKatsHouse);
// outputs "Dan, House - 1000 sq. ft." as expected
Console.WriteLine(dan);
Person kat = new Person("Kat", danAndKatsHouse);
// outputs "Kat, House - 1000 sq. ft.", again as expected
Console.WriteLine(kat);
Person john = new Person("John", johnsHouse);
// outputs "John, House - 2000 sq. ft.", so far so good...
Console.WriteLine(john);
// but what's this? suddenly dan and kat's house has changed?
// outputs "Dan, House - 2000 sq. ft."
Console.WriteLine(dan);
There's a difference between multiple objects of one class sharing the same object and ALL objects of that class sharing the same object. In the latter case, a static property makes sense; otherwise, it does not.
There are a few ways off the top of my head to deal with this scenario. They are:
1. Make the House property non-static
It might seem strange, but you can always just make the House property non-static and you won't ever have to worry about the problem above. Furthermore, assuming you actually do assign the same House object to each Person who shares it, making a change to the House through one Person object will actually achieve the desired effect:
House danAndKatsHouse = new House(1000.0);
// (after making Person.House property non-static)
Person dan = new Person("Dan", danAndKatsHouse);
Person kat = new Person("Kat", danAndKatsHouse);
dan.House.SquareFootage = 1500.0;
// outputs "1500"
Console.WriteLine(kat.House.SquareFootage);
This could actually be a problem, however, if you accidentally assign the same House to two people with the intention of them actually having two different Houses:
House smallerHouse = new House(1000.0);
House biggerHouse = new House(2000.0);
Person dan = new Person("Dan", smallerHouse);
Person john = new Person("John", biggerHouse);
Person bill = new Person("Bill", smallerHouse);
bill.House.SquareFootage = 1250.0;
// yikes, Dan's house just changed...
Console.WriteLine(dan);
2. Use a database
The fact is that the notion of making a house a property of a person is somewhat a forced concept to begin with. A person may move out of their house, different people may move in, etc. Really a relationship exists between the two, which makes using a database an appropriate solution.
Using this approach, what you'd do is have a Persons table, a Houses table, and a third table (maybe PersonHouses) containing id pairs from the other two tables to represent, I guess, home ownership.
If you don't have a full-blown database at your disposal, you can achieve effectively the same result (in .NET) using a System.Data.DataSet and its collection of System.Data.DataTable objects in your code. However, in any scenario where you are translating rows of a database (or DataTable) to objects and then back again, you do need to be aware of impedence mismatch. Basically, whatever meticulous precautions you take in your code to encapsulate your data are out the window once that data is in the database, ready to be modified by anyone with sufficient permissions.
3. Use dictionaries
Another approach, similar to using a database but a bit more work (and I think some programmers who've gone the DataSet route shudder at the thought of this), is to use dictionaries to keep track of your Person and House objects. The quickest way to implement this approach would be to have a Dictionary<int, Person> and a Dictionary<int, House>, and assign each Person a HouseId property:
public class Person {
public int Id { get; private set; }
public string Name { get; set; }
public int HouseId { get; set; }
private static int LastIdValue { get; set; }
private static Dictionary<int, Person> People { get; set; }
static Person() {
LastIdValue = 0;
People = new Dictionary<int, Person>();
}
// make the constructor private to disallow direct instantiation
private Person(int id, string name, int houseId) {
Id = id;
Name = name;
HouseId = houseId;
}
// only permit construction through this function, which inserts
// the new Person into the static dictionary before returning it
static public Person NewPerson(string name, int houseId) {
Person p = new Person(LastIdValue++, name, houseId);
People.Add(p.Id, p);
return p;
}
static public Person getPersonById(int id) {
Person p = null;
return People.TryGetValue(id, out p) ? p : null;
}
}
public class House {
public int Id { get; private set; }
public int SquareFootage { get; set; }
private static int LastIdValue { get; set; }
private static Dictionary<int, House> Houses { get; set; }
static House() {
LastIdValue = 0;
Houses = new Dictionary<int, House>();
}
// make the constructor private to disallow direct instantiation
private House(int id, int sqft) {
Id = id;
SquareFootage = sqft;
}
// only permit construction through this function, which inserts
// the new House into the static dictionary before returning it
static public House NewHouse(int sqft) {
House h = new House(LastIdValue++, sqft);
Houses.Add(h.Id, h);
return h;
}
static public House getHouseById(int id) {
House h = null;
return Houses.TryGetValue(id, out h) ? h : null;
}
}
House firstHouse = House.NewHouse(1000.0);
House secondHouse = House.NewHouse(2000.0);
Person dan = Person.NewPerson("Dan", firstHouse.Id);
Person kat = Person.NewPerson("Kat", firstHouse.Id);
Person john = Person.NewPerson("John", secondHouse.Id);
House dansHouse = House.getHouseById(dan.HouseId);
House katsHouse = House.getHouseById(kat.HouseId);
// this prints
if (katsHouse == dansHouse) { Console.WriteLine("Dan and Kat live in the same house."); }
// this also prints
if (dansHouse == firstHouse) { Console.WriteLine("Dan and Kat live in the first house."); }
// this does not print
if (dansHouse == secondHouse) { Console.WriteLine("Dan and Kat live in the second house."); }
This way, all your data encapsulation still holds. However, if you ever need your data to persist between instances of your code running, then you need to serialize your dictionaries in some file format (most likely XML), which could then be edited by anyone with sufficient privileges, and then you're back to the impedence mismatch problem of using a database all over again.
In light of the advantages and disadvantages of each approach, I think what actually makes the most sense -- and makes your life easiest -- is to simply make House a non-static property. This is assuming you don't have tons and tons of Person and House objects to keep track of.
" if I had a person class with a
property called Name (and just that
one property), and I am not modifying
that property then my class can be set
as static"
That is not correct. A person class is almost certainly a domain entity. It is conceivable you might want to have a static method on a Person entity, but I haven't ever come across one. In your example, you would have a private setter for your 'Name' property.
The static-ness of anything should model your domain, rather than being a language implementaion detail.
There are no true globl variables in C#, in the sense that that term is used in other languages like C. The difference between a static object and a global object is that a static object has permissions that are relative to the class in which it is defined. This is a very good thing, because you can create private static members that are only accessible to member of one class. The big problem with the abuse of global variables is the many depenencies to a single global variable that can evolve across a large colleciton of modules. Private static object avoid this problem.
One big problem with static objects is that they are not thread safe. In order to declare a thread safe static object, you must use the ThreadStatic attribute and provide a way for the object to be initialized on first access. You should do this for all multi-threaded environents e.g. ASP.NET, and any general purpose library that might run in multi-threaded environment. Heck, just always do this and you won't be sorry!
If you have a Person class with a static field name:
public class Person {
public static string Name { get; set; }
}
then you can only ever have one name. You can not have a list of persons with different names. Static can be seen as "Unique" in the way that it's value is global. This can be a trap in ASP.net applications by the way, because static applies through the entire application, which means to all users.
Static variables are rather rare and used for data that is really not part of a specific instance of the class. Or to return specific instances.
For example, Guid.Empty is a static field that returns a Guid that has all Bits set to 0.
A good example is System.Drawing.Color. Color has instance-specific variables, for example R,G,B and Alpha, but you have static fields like Color.Black which returns a Black color.

Categories

Resources