FAQ
Unlike reference types, you cannot assign a null into a value type. This is often a problem when interacting with code that interprets a null as having no value, rather than no-reference. The canonical example is database null values in columns that have representation as types such as int or DateTime. To address that, the System namespace provides the structure Nullable defined as:
public interface INullableValue
{
bool HasValue{get;}
object Value{get;}
}
[Serializable]
public struct Nullable : INullableValue,IEquatable>,... where T : struct
{
public Nullable(T value);
public bool HasValue{get;}
public T Value{get;}
public T GetValueOrDefault();
public T GetValueOrDefault(T defaultValue);
public bool Equals(Nullable other);
public static implicit operator Nullable(T value);
public static explicit operator T(Nullable value);
//More members
}
Because the Nullable struct uses a generic type parameter, you can use it to wrap a value type, and assign null into it:
Nullable<int> number = 123;
Debug.Assert(number.HasValue);
number = null;
Debug.Assert(number.HasValue == false);
Debug.Assert(number.Equals(null));
Once a null is assigned to a nullable type, you can still access it to verify if it has a value, via the HasValue property, or just equate it to null.
In C# and Visual Basic, you can even use the underlying value type's operators on a nullable type:
Nullable<int> number = 0;
number++;
The reason this is possible is because the compiler is capable of verifying that the underlying type supported the operator, and applying it on the value stored in the structure. This is called lifted operators.
The Nullable struct also provides conversion operators, so you can convert a nullable type to and from a real value type:
Nullable<int> nullableNumber = 123;
int number = (int)nullableNumber;
Debug.Assert(number == 123);
number = 456;
nullableNumber = number;
Debug.Assert(nullableNumber.Equals(456));
Note that using Nullable on Nullable is disallowed, and the compiler will issue an error:
//This will not compile:
Nullable<Nullable<int>> number = 123;
You can use the overloaded methods GetValueOrDefault() of Nullable to defensively obtain either the value stored in the nullable type or it its default, if it does contain a null:
Nullable<DateTime> time = null;
DateTime value = time.GetValueOrDefault();
Debug.Assert(value.ToString() == "1/1/0001 12:00:00 AM");
The System namespace also defines the static helper class Nullable and the helper class NullableConverter, but those are not needed usually.
The C# 2.0 compiler supports shorthand for Nullable. You can use the ? modifier on value types to actually construct a Nullable around it:
int? number = 123;
Debug.Assert(number.HasValue);
number = null;
Debug.Assert(number.HasValue == false);
Note that the type declared by the ? modifier is identical to that created using Nullable directly:
Debug.Assert(typeof(int?) == typeof(Nullable<int>));
As with using Nullable directly, the compiler supports lifted operators. Whenever you combine nullable types using operators, if any one of them is null, then the resulting expression will be null too:
int? number1 = 123;
int? number2 = null;
int? sum = number1 + number2;
Debug.Assert(sum == null);
Using the ? modifier is the common way of declaring and using nullable variables in C#. You can even pass nullable types as type arguments for generic types:
IList<int?> list = new List<int?>();
list.Add(3);
list.Add(null);
C# 2.0 also provides the null coalescing operator via the ?? operator.
c = a ?? b;
The result of applying the ?? operator on two operands returns the left hand side operand (a) if it is not null, and the right operand (b)otherwise. While b can of course be null too, you typically use the ?? operator to supply a default value in case a is null.
Summary
- Nullable types represent value-type variables that can be assigned the value of null. You cannot create a nullable type based on a reference type. (Reference types already support the null value.)
- The syntax T? is shorthand for System.Nullable, where T is a value type. The two forms are interchangeable.
- Assign a value to a nullable type in the same way as for an ordinary value type, for example int? x = 10; or double? d = 4.108;
- Use the System.Nullable.GetValueOrDefault method to return either the assigned value, or the default value for the underlying type if the value is null, for example int j = x.GetValueOrDefault();
- Use the HasValue and Value read-only properties to test for null and retrieve the value, for example if(x.HasValue) j = x.Value;
- The HasValue property returns true if the variable contains a value, or false if it is null.
- The Value property returns a value if one is assigned, otherwise a System.InvalidOperationException is thrown.
- The default value for a nullable type variable sets HasValue to false. The Value is undefined.
- Use the ?? operator to assign a default value that will be applied when a nullable type whose current value is null is assigned to a non-nullable type, for example int? x = null; int y = x ?? -1;
- Nested nullable types are not allowed. The following line will not compile: Nullable<Nullable<int>> n;
Source : MSDN
An agile software development methodology developed by Ken Schwaber and Jeff Sutherland in the mid 1990s. Scrum is based on a "Sprint," which is a 30-day period for delivering a working part of the system. Each Sprint starts with a two to three-hour planning session that includes the customer (product owner), the facilitator (Scrummaster) and the cross-functional team. The customer describes the highest priority in the backlog, and after the team agrees on how much of it to do, it is left alone to do it. To keep the team synchronized, there is a 15-minute meeting every day. At the end of the Sprint, the results are delivered and reviewed, and the next Sprint is started.
Scrum projects support the use of any software engineering discipline. However, since XP (Extreme Programming) and Scrum share many core practices, Scrum and XP integrate well together. The name comes from Rugby, where a scrum is the mechanism for getting the ball moving after it has gone out of play.
Characteristics of Scrum
- Scrum is an agile process to manage and control development work.
- Scrum is a wrapper for existing engineering practices.
- Scrum is a team-based approach to iteratively, incrementally develop systems and products when requirements are rapidly changing
- Scrum is a process that controls the chaos of conflicting interests and needs.
- Scrum is a way to improve communications and maximize co-operation.
- Scrum is a way to detect and cause the removal of anything that gets in the way of developing and delivering products.
- Scrum is a way to maximize productivity.
- Scrum is scalable from single projects to entire organizations. Scrum has controlled and organized development and implementation for multiple interrelated products
- and projects with over a thousand developers and implementers.
- Scrum is a way for everyone to feel good about their job, their contributions, and that they have done the very best they possibly could.
Managed code is code that is written to target the services
of the Common Language Runtime (see What is the Common Language Runtime?). In
order to target these services, the code must provide a minimum level of
information (metadata) to the runtime. All C#, Visual Basic.NET, and JScript.NET
code is managed by default. Visual Studio.NET C++ code is not managed by
default, but the compiler can produce managed code by specifying a command-line
switch (/CLR).
Closely related to managed code is managed data—data that is
allocated and de-allocated by the Common Language Runtime's garbage collector.
C#, Visual Basic, and JScript.NET data is managed by default. C# data can,
however, be marked as unmanaged through the use of special keywords. Visual
Studio.NET C++ data is unmanaged by default (even when using the /CLR switch),
but when using Managed Extensions for C++, a class can be marked as managed by
using the __gc keyword. As the name suggests, this means that the memory for
instances of the class is managed by the garbage collector. In addition, the
class becomes a full participating member of the .NET Framework community, with
the benefits and restrictions that brings. An example of a benefit is proper
interoperability with classes written in other languages (for example, a managed
C++ class can inherit from a Visual Basic class). An example of a restriction is
that a managed class can only inherit from one base class.
The assembly resolution is controlled by the configuration properties for the application domain such as System.AppDomainSetup.ApplicationBase. The configuration properties may not be sufficient in some hosting scenarios, especially if the host is creating assemblies in memory on the fly using Reflection Emit, since there may not be an assembly on disk to find. In such cases, you can use the System.AssemblyResolve event to hook into the type loading process.
The AssemblyResolve event is defined as follows:
public event ResolveEventHandler AssemblyResolve;
where System.ResolveEventHandler is defined as follows:
public delegate Assembly ResolveEventHandler(Object sender, ResolveEventArgs args);
The args parameter to ResolveEventHandler is the identity of the assembly the runtime is seeking. The receipient of the event is free to resolve the reference to the assembly by any means. For example, the receipient may construct an assembly on the fly, find it in a custom location on disk, etc. The only requirement is that the receipient return a instance of System.Reflection.Assembly.
A type is resolved dynamically by defining a handler for the TypeResolve event. The TypeResolve event is defined as follows:
public event ResolveEventHandler TypeResolve;
A resource is resolved dynamically by defining a handler for the ResourceResolve event. The ResourceResolve event is defined as follows:
public event ResolveEventHandler ResourceResolve;
For both types and resources, the handler must resolve the assembly in which the entity is defined. The code for the handler is very similar to the handler shown in the sample above.
The struct type is suitable for representing lightweight objects such as
Point, Rectangle, and Color. Although it is possible to represent a point as a
class, a struct is more efficient in some scenarios. For example, if you declare
an array of 1000 Point objects, you will allocate additional memory for
referencing each object. In this case, the struct is less expensive.
When you create a struct object using the new operator, it gets created and
the appropriate constructor is called. Unlike classes, structs can be
instantiated without using the new operator. If you do not use new, the fields
will remain unassigned and the object cannot be used until all of the fields are
initialized.
It is an error to declare a default (parameterless) constructor for a struct.
A default constructor is always provided to initialize the struct members to
their default values.
It is an error to initialize an instance field in a struct.
There is no inheritance for structs as there is for classes. A struct cannot
inherit from another struct or class, and it cannot be the base of a class.
Structs, however, inherit from the base class Object. A struct can implement
interfaces, and it does that exactly as classes do.
A struct is a value type, while a class is a reference type.
Following are the various IsolationLevels:
Serialized : Data read by a current transaction cannot be
changed by another transaction until the current transaction finishes. No new
data can be inserted that would affect the current transaction. This is the
safest isolation level and is the default.
Repeatable Read : Data read by a current transaction cannot
be changed by another transaction until the current transaction finishes. Any
type of new data can be inserted during a transaction.
Read Committed : A transaction cannot read
data that is being modified by another transaction that has not committed. This
is the default isolation level in Microsoft SQL Server.
Read Uncommitted : A transaction can read any data, even if
it is being modified by another transaction. This is the least safe isolation
level but allows the highest concurrency.
Any : Any isolation level is supported. This setting is most
commonly used by downstream components to avoid conflicts. This setting is
useful because any downstream component must be configured with an isolation
level that is equal to or less than the isolation level of its immediate
upstream component. Therefore, a downstream component that has its isolation
level configured as Any always uses the same isolation level that its immediate
upstream component uses. If the root object in a transaction has its isolation
level configured to Any, its isolation level becomes Serialized.
With the release of Visual Studio 2005, the C# language has been updated to
version 2.0, which supports the following new features:
Generics
Generic types are added to the language to
enable programmers to achieve a high level of code reuse and enhanced
performance for collection classes. Generic types can differ only by arity.
Parameters can also be forced to be specific types.
Iterators
Iterators make it easier to dictate how a
foreach loop will iterate over a collection's contents.
Partial Classes
Partial type definitions allow a single
type, such as a class, to be split into multiple files. The Visual Studio
designer uses this feature to separate its generated code from user code.
Nullable Types
Nullable types allow a variable to contain
a value that is undefined. Nullable types are useful when working with databases
and other data structures that may contain elements that contain no specific
values.
Anonymous Methods
It is now possible to pass a block of
code as a parameter. Anywhere a delegate is expected, a code block can be used
instead: there is no need to define a new method.
Namespace alias qualifier
The namespace alias qualifier
(::) provides more control over accessing namespace members. The global :: alias
allows access the root namespace that may be hidden by an entity in your
code.
Static Classes
Static classes are a safe and convenient
way of declaring a class containing static methods that cannot be instantiated.
External Assembly Alias
Reference different versions of
the same component contained in the same assembly with this expanded use of the
extern keyword.
Property Accessor Accessibility
It is now possible to
define different levels of accessibility for the get and set accessors on
properties.
Covariance and Contravariance in Delegates
The method
passed to a delegate may now have greater flexibility in its return type and
parameters.
Declare, Instantiate, and Use a Delegate
Method group
conversion provides a simplified syntax for declaring delegates.
Fixed Size Buffers
In an unsafe code block, it is now
possible to declare fixed-size structures with embedded arrays.
Friend Assemblies
Assemblies can provide access to
non-public types to other assemblies.
Inline warning control
The #pragma warning directive may
be used to disable and enable certain compiler warnings.
volatile
The volatile keyword can now be applied to
IntPtr and UIntPtr.
The C# compiler introduces the following additions and changes for this
release:
/errorreport option
Can be used to report internal
compiler errors to Microsoft over the Internet.
/incremental option
Has been removed.
/keycontainer and /keyfile options
Support specifying
cryptographic keys.
/langversion option
Can be used to specify compatibility
with a specific version of the language.
/linkresource option
Contains additional options.
/moduleassemblyname option
Allows you to build a
.netmodule file and access non-public types in an existing assembly.
/pdb option
Specifies the name and location of the .pdb
file.
/platform option
Enables you to target Itanium Family
(IPF) and x64 architectures.
#pragma warning
Used to disable and enable individual
warnings in code.
Generics have native support in IL and the CLR itself. When you compile
generic server-side code, the compiler compiles it into IL, just like any other
type. However, the IL only contains parameters or place holders for the actual
specific types. In addition, the metadata of the generic server contains generic
information such as constraints.
The client-side compiler uses that generic metadata to support type safety.
When the client provides a type arguments, the client's compiler substitutes the
generic type parameter in the server metadata with the specified type. This
provides the client's compiler with type-specific definition of the server, as
if generics were never involved. At run time, the actual machine code produced
depends on whether the specified types are value or reference type. If the
client specifies a value type, the JIT compiler replaces the generic type
parameters in the IL with the specific value type, and compiles it to native
code. However, the JIT compiler keeps track of type-specific server code it
already generated. If the JIT compiler is asked to compile the generic server
with a value type it has already compiled to machine code, it simply returns a
reference to that server code. Because the JIT compiler uses the same
value-type-specific server code in all further encounters, there is no code
bloating.
If the client specifies a reference type, then the JIT compiler replaces the
generic parameters in the server IL with object, and compiles it into native
code. That code will be used in any further requests for a reference type
instead of a generic type parameter. Note that this way the JIT compiler only
reuses actual code. Instances are still allocated according to their size off
the managed heap, and there is no casting.
A theme is a collection of property settings that allow you to define the
look of pages and controls, and then apply the look consistently across pages in
a Web application, across an entire Web application, or across all Web
applications on a server.
Cascading Style Sheets (CSS) is a stylesheet language used to describe the
presentation of a document written in a markup language(i.e HTML).
Themes are similar to cascading style sheets in that both themes and style
sheets define a set of common attributes that can be applied to any page.
However, themes differ from style sheets in the following ways:.
- Themes are control-based, not HTML-based. Themes can define many properties
of a control or page, not just style properties. For example, using themes, you
can specify the graphics for a TreeView control, the template layout of a
GridView control, and so on.
- Themes do not cascade the way style sheets do. For example, by default,
property values override local property values unless you explicitly apply the
theme as a style sheet theme.
- Only one theme can be applied to each page. You cannot apply multiple themes
to a page, unlike style sheets where multiple style sheets can be applied.
- Themes are applied on the server where as stylesheet on the client side.
- Themes can be applied through configuration files.
Yes. The following tag creates an instance of a custom type named
ShoppingCart and assigns it session scope (that is, it creates a unique
ShoppingCart instance for each and every session created on the server):
<object id="MyShoppingCart" class="ShoppingCart"
scope="session" runat="server" />
Managed types created this way are identified by class name. Unmanaged types
(COM classes) are identified by CLSID or ProgID.
When a TextBox control has its TextMode property set to Password, you cannot
assign a default value to the control using the standard Text property. In order
to assign a default value, you need to use code that looks like this:
C# Version
txtPassword.Attributes["value"] = "default value";
VB.NET Version
txtPassword.Attributes("value") = "default value"
To be able to join tables between two SQL Servers, first you have to link them. After the linked servers are setup, you just have to prefix your tables names with server name, database name, table owner name in your SELECT queries. The following example links SERVER_01 to SERVER_02. Execute the following commands in SERVER_02:
EXEC sp_addlinkedserver SERVER_01
GO
/* The following command links 'sa' login on SERVER_02 with the 'sa' login of SERVER_01 */
EXEC sp_addlinkedsrvlogin @rmtsrvname = 'SERVER_01', @useself = 'false', @locallogin = 'sa', @rmtuser = 'sa', @rmtpassword = 'sa password of SERVER_01'
GO
SELECT a.title_id
FROM SERVER_01.pubs.dbo.titles a
INNER JOIN SERVER_02.pubs.dbo.titles b
ON a.title_id = b.title_id
GO
Full Assembly reference: A full assembly reference includes
the assembly's text name, version, culture, and public key token (if the
assembly has a strong name). A full assembly reference is required if you
reference any assembly that is part of the common language runtime or any
assembly located in the global assembly cache.
Partial Assembly
reference: We can dynamically reference an assembly by providing only
partial information, such as specifying only the assembly name. When you specify
a partial assembly reference, the runtime looks for the assembly only in the
application directory.
We can make partial references to an assembly in
your code one of the following ways:
- Use a method such as System.Reflection.Assembly.Load and specify only a
partial reference. The runtime checks for the assembly in the application
directory.
- Use the System.Reflection.Assembly.LoadWithPartialName method and specify
only a partial reference. The runtime checks for the assembly in the application
directory and in the global assembly cache
The Common Language Runtime is the execution engine for .NET Framework applications.
It provides a number of services, including the following:
- Code management (loading and execution)
- Application memory isolation
- Verification of type safety
- Conversion of IL to native code
- Access to metadata (enhanced type information)
- Managing memory for managed objects
- Enforcement of code access security
- Exception handling, including cross-language exceptions
- Interoperation between managed code, COM objects, and pre-existing DLLs (unmanaged code and data)
- Automation of object layout
- Support for developer services (profiling, debugging, and so on)
An AppDomain can be thought of as a lightweight process. Multiple AppDomains can exist inside a Win32 process. The primary purpose of the AppDomain is to isolate applications from each other, and so it is particularly useful in hosting scenarios such as ASP.NET. An AppDomain can be destroyed by the host without affecting other AppDomains in the process.
Win32 processes provide isolation by having distinct memory address spaces. This is effective, but expensive. The .NET runtime enforces AppDomain isolation by keeping control over the use of memory - all memory in the AppDomain is managed by the .NET runtime, so the runtime can ensure that AppDomains do not access each other's memory.
One non-obvious use of AppDomains is for unloading types. Currently the only way to unload a .NET type is to destroy the AppDomain it is loaded into. This is particularly useful if you create and destroy types on-the-fly via reflection.
It is important to note that only type-safe code can be managed in this way (the runtime cannot guarantee isolation when unsafe code is loaded in an application domain).
Some of the advantage of using AppDomain are:
- AppDomain are far less expensive in terms of processing power and memory than a full blown process.
- AppDomain provide a deeper level of isolation for hosting a loaded application. In one AppDomain within a process fails, the remaining AppDomains remain functional.
- An application cannot directly access code or resource in another application.