- Memory
- What is the difference between a primitive type and a reference type?
- What does the garbage collector do?
- Handles memory de-allocation for objects
- How is it implemented? A rough approximation is fine.
- Basic algorithm
- Model as a directed graph
- Each object instance is a vertex
- Each reference to an instance is an edge (So if one object references another, then there is a directed edge from one to the other)
- Every so often, a depth first search occurs
-
- All objects that are visited are considered “marked”
- Therefore, unmarked objects are no longer referenced
- Once the available memory is used, a “sweep” occurs where memory for all unmarked objects is released
- The method described is called mark and sweep garbage collection.
- What is generational garbage collection?
- Some objects exist for longer times than other objects. They do not need to be continuously checked in the mark and sweep algorithm described above
- When a sweep occurs, marked objects get promoted to a different graph (a generation) that is not processed as frequently
- C# has 3 generations
- What is the difference between Finalize and Dispose?
- Finalize is a destructor for an object and gets called when the garbage collector destroys the object. The programmer does not determine when finalize gets called.
- IDisposable, on the other hand, allows programmers to determine when an object can be destroyed by calling Dispose. This allows programmatic release of resources like database connections. Note that the memory still is not released until the garbage collector reclaims it.
- Why would someone want to implement IDisposable?
- One common reason is to ensure efficient use of limited resources like database connections
- Another use would be to wrap processes that have specific code that needs to be called at a start and finish point (ie, a database transaction block)
- How could someone use the using statement to implement IDisposable?
- using(MyObject obj = new MyObject()){ … }
- When execution reaches the close }, MyObject’s Dispose method is called
- What is a WeakReference? Why would you use one?
- A reference that doesn’t prevent garbage collection
- An example use would be to maintain a cache
- What is the difference between stack memory and heap memory?
- Stack – contains memory for primitive types & pointers
- Heap – used to allocate memory for objects that are created
- What are the memory considerations when using recursion with many levels?
- What is boxing and unboxing?
- Boxing – the term use to describe the movement of values from the stack to the heap (so change a value type to a reference type)
- Unboxing – from heap to stack
CLR
- What is CLR?
- Common Language Runtime – This is a virtual machine (or execution engine depending on who is defining it) that runs generic code meant for multiple hardware configurations (http://blogs.msdn.com/b/brada/archive/2005/01/12/351958.aspx)
- What is CLI?
- Common Language Infrastructure – a specification that .net languages are built on. The CLR is an implementation of the CLI
- What is CIL?
- Common Intermediate Language – .net languages such as C# get compiled to CIL bytecode. This format is understood by the CLR
- What is JIT?
- Just In Time compiler - CIL is compiled at runtime as needed into native code
- It executes code by using a hybrid of interpreted and ahead-of-time approach. Code is first interpreted and then the compilied commands are cached for later use.
- How can JIT code be faster than ahead of time compiled code?
- The JIT code is interpreted for an computer’s specific hardware configuration whereas ahead-of-time compilied code is written for a set of computers meeting a more general specification. This means the JIT can take advantage of very specific hardware features.
- Explain the path from C# source to native code
- C# gets compiled to CIL
- CIL is then executed by the CLR. It does this using a JIT compiler which converts the CIL into native code
Assemblies
- What is the difference between a service and a standard exe?
- What is the difference between an exe and a dll?
- DLL is a library of useful code that can be used by other code when referenced
- EXEs also have this ability as well. However, they also offer an entry point that is able to start executing commands
- What is DLL hell?
- DLL hell refers to a set of problems caused by DLL sharing in applications before .net. Multiple programs may share one dll. When a new program is installed, it may overwrite a previously installed shared DLL with a newer version. This version may not be backwards compatible breaking programs that were previously running correctly.
- What is an assembly qualified name?
- It is a way to ensure that a type is associated with the proper assembly binary
- TopNamespace.SubNameSpace.ContainingClass+NestedClass, MyAssembly, Version=1.3.0.0, Culture=neutral, PublicKeyToken=b17a5c561934e089
- What is the GAC? What does the GAC do?
- The GAC is the global assembly cache.
- It stores assemblies that are meant to be shared but avoids DLL mentioned above (by using assembly qualified names)
- How do you add assemblies to the GAC?
- The most common way is to use a windows installer
- Using gacutil.exe is another method
Misc
- What is reflection?
- Reflection offers the ability to find information about types at runtime and use that information to dynamically create instances and call methods and properties
- What are some examples of uses for reflection?
- Custom serialization
- Custom binding
- ORM mapping
- What is the difference between a.Equals(b) and a == b?
- For value types, the expressions are the same
- For reference types, a==b is true only when the objects have the same reference (pointer)
- a.Equals(b), on the other hand, is true for reference types with different pointers provided they have the same value. An example usage would be for a class that is mapped to a database table. There could be two different instances of the class with an id of 5. When using ==, the value would return false. However, if Equals is appropriately overridden to compare the id, than a.Equals(b) should return true since they have the same id
Primitive Type implementations
Knowing details about primitive types is essential when dealing
with many activities like efficiency, boundaries, and memory usage and
is something senior developers should be able to at least approximate.
If you don’t know this table, you will never think about it. However,
once you know it, you will be surprised at how often you take these
addition details into consideration when developing code.
Type | Size | Range (signed) | Range (unsigned) | Order | Precision |
boolean | 8 bits | 0 to 1 | |||
byte | 8 bits | -128 to 128 | 0 to 256 | 102 | |
short | 16 bits | -32,768 to 32,767 | 0 to 65535 | 104 | |
int | 32 bits | -2,147,483,648 to 2,147,483,647 | 0 to 4,294,967,295 | 109 | |
long | 64 bits | -922337203685477508 to 922337203685477507 | 0 to 18446744073709551615 | 1019 | |
float | 32 bits | -3.402823e38 to 3.402823e38 | 1038 | 7 digits | |
double | 64 bits | -1.79769313486232e308 to 1.79769313486232e308 | 10308 | 15-16 digits | |
decimal | 128 bits | ±1.0 × 10e−28 to ±7.9 × 10e28 | 1028 | 29 digits | |
char | 16 bits | 0 to 65535 | 104 |
No comments :
Post a Comment