Currently showing entries with the tag: Immutable String
|
page 1 of 1
|
.NET Interview Questions - Part 2
August 26, 2007 • 9:41PM • permalink
Part 1 can be found here.
Continuing where we left off...
3) What does the term "immutable string" mean?
Strings in C# are immutable, meaning that the string object cannot be modified once it has been instantiated. Take a look at the following:
string s1 = "Hello, my name is ";
s1 += "adam";
While it appears that the string 'adam' is simply being appended to the original string, a lot more work is taking place on the back end. Since the string s1 is immutable, it can't be changed. Implicitly, c# is creating a new buffer in memory that can hold both the "My name is " and "adam". Once this new buffer is filled (and a new string object is created) s1 is assigned the new reference and the old references eventually become garbage collected.
If you read my blog entry on the System.Diagnostics.Stopwatch class, you saw that this can have a huge effect on the performance of an application.
In the Stopwatch blog entry, I used the string.Concat method in the optimized test. While that method outperforms the standard += operator (and can be further optimized by using the overloaded version that allows passing in four string parameters), there is an even better way, for doing many append operations.
using System.Text;
StringBuilder sb = new StringBuilder();
string letters = "abcdefghijklmnopqrstuvwxyz";
int iterations = 100000;
for (int i = 0; i < iterations; ++i)
sb.Append(letters[i % 26]);
In my tests, the StringBuilder class' Append method was twice as fast as using string.Concat. This is because the StringBuilder class has preallocated a buffer of memory upon initialization, which the string.Concat object is still creating extra immutable string objects that aren't needed.
4) Describe the concept of lazy-initialization in OOP?
Lazy-initialization is best shown with a working example...
Let us take for instance that we have a class that represents a Building, perhaps for a game. In this Building class, we have various properties to represent the different rooms that you might find in the building.
For sake of this argument, let us also suppose that the general architecture of the game dictates that the Building class reference is going to be persisted in a database and not in static memory (maybe it's web-based). When we create the instance of the Building object, it would be a huge mistake to instantiate all the various rooms of the Building in the constructor.
There could be a Kitchen, a JanitorCloset, a SupplyRoom, a Gym, a Hallway or maybe even Bathroom[]. If only one of the above is used in the current execution, then we would waste a lot of processing on both the web server and possibly on either a cache server or a database server (or both), retrieving data for the rooms we don't need. This is a very common mistake that is made by developers that are new to OOP.
Lazy-initialization can help us improve our performance by only creating the objects as they are needed. Like in the following example:
public class Building
{
private Room kitchen;
private Room supply_room;
...
public Room Kitchen
{
get {
if (kitchen == null)
kitchen = new Room(building_id, 'kitchen');
return kitchen;
}
}
public Room SupplyRoom
{
get {
if (supply_room == null)
supply_room= new Room(building_id, 'supply_room');
return supply_room;
}
}
}
In the code above, the first time the Kitchen or SupplyRoom properties are used, their associated private fields will be null and will be instantiated through their respective Room constructors. If they aren't used in a given request, they won't be instantiated at all!
5) Write a Generic Method that takes one parameter of any type and returns the same type that is passed in.
This question really isn't fair, but we like to throw it out there anyways. We don't base any candidate on their ability to answer it (because although 1 person actually got close, nobody has ever answered such a simple question). This is actually one of the first questions we ask, mostly to set the bar. Most of the time we see a person writing a function that attempts to use Generics, which is better than some other things I've seen... (Note that this is a .NET 2.0 specific feature)
The solution is actually very simple:
using System.Collections.Generic;
public T SomeFunc<T>(T obj)
{
T new_object_copy = obj;
return new_object_copy;
}
That's it! I only added the line T new_object_copy = obj to do something more interesting than just return the object.
We can now call this with virtually any type we want!
string s = SomeFunc<string>("hi");
int i = SomeFunc<int>(5);
my_class m = SomeFunc<my_class>(new my_class());
As a bonus, you can constrain the types of objects that you want to allow the function to operate on by adding a where clause:
public T SomeFunc<T>(T obj) where T : IList, IEnumerable
{
T new_object_copy = obj;
return new_object_copy;
}
List l = new List<string>();
List l2 = SomeFunc<List<string>>(l);
string s = SomeFunc<string>("hi");
Simple!
Maybe so, but we've yet to see somebody answer it correctly (and I've done literally fifty interviews in the last six months). We even joke around the office that if somebody can answer it correctly, they are an "instant hire". (Offer now null and void, since I've given the solution away.)

.NET Quickies
* What is the C# coalesce operator and how is it used?
The coalesce operator in C# is the ?? operator. It is used to do a conditional assignment to a variable, evaluating from left to right and stopping on the first non-null result. For example:
string a = null;
string b = "Yay!";
string c = a ?? b;
* What is the size (in bytes) of the following data types on a 32-bit machine: byte, short, int, float and double?
byte = 1 byte
short = 2 bytes
int = 4 bytes
float = 4 bytes
double = 8 bytes
* What is the result of bit-shifting an integer (either to the right or the left)?
Bit-shifting an integer to the left will multiply the number by two for each bit shifted.
Bit-shifting an integer to the right will divide the number by two for each bit shifted.
I could talk about simple interview questions forever! I'm sure that I will have much more to write about on this topic in the future!
Continuing where we left off...
3) What does the term "immutable string" mean?
Strings in C# are immutable, meaning that the string object cannot be modified once it has been instantiated. Take a look at the following:
string s1 = "Hello, my name is ";
s1 += "adam";
While it appears that the string 'adam' is simply being appended to the original string, a lot more work is taking place on the back end. Since the string s1 is immutable, it can't be changed. Implicitly, c# is creating a new buffer in memory that can hold both the "My name is " and "adam". Once this new buffer is filled (and a new string object is created) s1 is assigned the new reference and the old references eventually become garbage collected.
If you read my blog entry on the System.Diagnostics.Stopwatch class, you saw that this can have a huge effect on the performance of an application.
In the Stopwatch blog entry, I used the string.Concat method in the optimized test. While that method outperforms the standard += operator (and can be further optimized by using the overloaded version that allows passing in four string parameters), there is an even better way, for doing many append operations.
using System.Text;
//Place this at the top...
StringBuilder sb = new StringBuilder();
string letters = "abcdefghijklmnopqrstuvwxyz";
int iterations = 100000;
for (int i = 0; i < iterations; ++i)
sb.Append(letters[i % 26]);
In my tests, the StringBuilder class' Append method was twice as fast as using string.Concat. This is because the StringBuilder class has preallocated a buffer of memory upon initialization, which the string.Concat object is still creating extra immutable string objects that aren't needed.
4) Describe the concept of lazy-initialization in OOP?
Lazy-initialization is best shown with a working example...
Let us take for instance that we have a class that represents a Building, perhaps for a game. In this Building class, we have various properties to represent the different rooms that you might find in the building.
For sake of this argument, let us also suppose that the general architecture of the game dictates that the Building class reference is going to be persisted in a database and not in static memory (maybe it's web-based). When we create the instance of the Building object, it would be a huge mistake to instantiate all the various rooms of the Building in the constructor.
There could be a Kitchen, a JanitorCloset, a SupplyRoom, a Gym, a Hallway or maybe even Bathroom[]. If only one of the above is used in the current execution, then we would waste a lot of processing on both the web server and possibly on either a cache server or a database server (or both), retrieving data for the rooms we don't need. This is a very common mistake that is made by developers that are new to OOP.
Lazy-initialization can help us improve our performance by only creating the objects as they are needed. Like in the following example:
public class Building
{
private Room kitchen;
private Room supply_room;
...
public Room Kitchen
{
get {
if (kitchen == null)
kitchen = new Room(building_id, 'kitchen');
return kitchen;
}
}
public Room SupplyRoom
{
get {
if (supply_room == null)
supply_room= new Room(building_id, 'supply_room');
return supply_room;
}
}
}
In the code above, the first time the Kitchen or SupplyRoom properties are used, their associated private fields will be null and will be instantiated through their respective Room constructors. If they aren't used in a given request, they won't be instantiated at all!
5) Write a Generic Method that takes one parameter of any type and returns the same type that is passed in.
This question really isn't fair, but we like to throw it out there anyways. We don't base any candidate on their ability to answer it (because although 1 person actually got close, nobody has ever answered such a simple question). This is actually one of the first questions we ask, mostly to set the bar. Most of the time we see a person writing a function that attempts to use Generics, which is better than some other things I've seen... (Note that this is a .NET 2.0 specific feature)
The solution is actually very simple:
using System.Collections.Generic;
//Place this at the top...
public T SomeFunc<T>(T obj)
{
T new_object_copy = obj;
return new_object_copy;
}
That's it! I only added the line T new_object_copy = obj to do something more interesting than just return the object.
We can now call this with virtually any type we want!
string s = SomeFunc<string>("hi");
int i = SomeFunc<int>(5);
my_class m = SomeFunc<my_class>(new my_class());
As a bonus, you can constrain the types of objects that you want to allow the function to operate on by adding a where clause:
public T SomeFunc<T>(T obj) where T : IList, IEnumerable
{
T new_object_copy = obj;
return new_object_copy;
}
List
List
//This will work
string s = SomeFunc<string>("hi");
//This will no longer compile
Simple!
Maybe so, but we've yet to see somebody answer it correctly (and I've done literally fifty interviews in the last six months). We even joke around the office that if somebody can answer it correctly, they are an "instant hire". (Offer now null and void, since I've given the solution away.)
.NET Quickies
* What is the C# coalesce operator and how is it used?
The coalesce operator in C# is the ?? operator. It is used to do a conditional assignment to a variable, evaluating from left to right and stopping on the first non-null result. For example:
string a = null;
string b = "Yay!";
string c = a ?? b;
//The value in b will be assigned to c
* What is the size (in bytes) of the following data types on a 32-bit machine: byte, short, int, float and double?
byte = 1 byte
short = 2 bytes
int = 4 bytes
float = 4 bytes
double = 8 bytes
* What is the result of bit-shifting an integer (either to the right or the left)?
Bit-shifting an integer to the left will multiply the number by two for each bit shifted.
Bit-shifting an integer to the right will divide the number by two for each bit shifted.
I could talk about simple interview questions forever! I'm sure that I will have much more to write about on this topic in the future!
0 comments
|
page 1 of 1
|