Jack @ ASP.NET

As a software engineer, I focus on .NET, especially asp.net, C#, WCF and so on, and I am also very interested in Search Engine Optimization.

Entries for the ‘C#’ Category

Optional Parameters in C# 4.0

Some members of the C# community were discussing optional parameters and the implications for future versions when optional parameter values change.  In short, you need to realize that changing the value of optional parameters in a public API is a change that is observable at client code. The ramifications vary greatly, from “no big” to “stop the world”. I’ll give a brief explanation of how the feature works, and what you need to watch for and how to separate reasonable caution from irrational fear from using a feature.

While most modern programming languages provide some way of declaring optional function parameters, C# doesn’t provide a way of directly doing so, despite the fact that VB.NET and .NET’s attribute system both support this functionality. This is a subject of some debate currently in the C# community. The C# development team’s position seems to boil down to the following: When provided, this feature is usually nothing more than dressing up method overloading with a little syntactic sugar.

When you get right down to it, their position makes some sense. A function with an optional parameter is in reality two different functions: one that assumes some default behavior if the optional parameter is omitted, and another that performs more specific behavior based on the value of the optional parameter if provided. But that doesn’t change the fact that using overloaded methods to provide optional parameter support feels a little clunky. It works, but you always wind up writing more code, and you pollute your object interface with the extra method signatures required to support all of your optional parameters. Let’s look at some alternatives.

Displaying Markers on the Chart via Microsoft Chart Controls

01 private void BindData() {
02
03 var exams = new List<Exam>()
04 {
05 new Exam() { Name = "Exam 1", Point = 10 },
06 new Exam() { Name = "Exam 2", Point = 12 },
07 new Exam() { Name = "Exam 3", Point = 15 },
08 new Exam() { Name = "Exam 4", Point = 2 }
09 };
10
11 var series = ExamsChart.Series["ExamSeries"];
12
13 foreach (var exam in exams) {
14
15 var point = new DataPoint();
16 point.SetValueXY(exam.Name, exam.Point);
17
18 point.Label = exam.Point.ToString();
19 series.Points.Add(point);
20 }
21
22 ExamsChart.DataSource = exams;
23 ExamsChart.DataBind();
24 }
Microsoft Chart

Microsoft Chart

Entity Framework 4

Some of the big improvements in EF4 include:

  • POCO Support: You can now define entities without requiring base classes or data persistence attributes.
  • Lazy Loading Support: You can now load sub-objects of a model on demand instead of loading them up front.
  • N-Tier Support and Self-Tracking Entities: Handle scenarios where entities flow across tiers or stateless web calls.
  • Better SQL Generation and SPROC support: EF4 executes better SQL, and includes better integration with SPROCs
  • Automatic Pluralization Support: EF4 includes automatic pluralization support of tables (e.g. Categories->Category).
  • Improved Testability: EF4’s object context can now be more easily faked using interfaces.
  • Improved LINQ Operator Support: EF4 now offers full support for LINQ operators.

EF4 enables you to:

  • Develop without ever having to open a designer or define an XML mapping file
  • Define your model objects by simply writing “plain old classes” with no base classes required
  • Use a “convention over configuration” approach that enables database persistence without explicitly configuring anything
  • Optionally override the convention-based persistence and use a fluent code API to fully customize the persistence mapping

C# Code Function: Converting List of strings to string

=== Program that converts List (C#) ===

using System;
using System.Collections.Generic;

class Program
{
    static void Main()
    {
        List<string> dogs = new List<string>(); // Create new list of strings
        dogs.Add("Aigi");                       // Add string 1
        dogs.Add("Spitz");                      // 2
        dogs.Add("Mastiff");                    // 3
        dogs.Add("Finnish Spitz");              // 4
        dogs.Add("Briard");                     // 5

        string dogCsv = string.Join(",", dogs.ToArray());
        Console.WriteLine(dogCsv);
    }
}

=== Output of the program ===

Aigi,Spitz,Mastiff,Finnish Spitz,Briard

Optional Parameters in C# 4.0

The definition of a method, constructor, indexer, or delegate can specify that its parameters are required or that they are optional. Any call must provide arguments for all required parameters, but can omit arguments for optional parameters.

Each optional parameter has a default value as part of its definition. If no argument is sent for that parameter, the default value is used. Default values must be constants.

Optional parameters are defined at the end of the parameter list, after any required parameters. If the caller provides an argument for any one of a succession of optional parameters, it must provide arguments for all preceding optional parameters. Comma-separated gaps in the argument list are not supported. For example, in the following code, instance method ExampleMethod is defined with one required and two optional parameters.

E.g.

public void ExampleMethod(int required, string optionalstr = "default string", int optionalint = 10)

The following call to ExampleMethod causes a compiler error, because an  argument is provided for the third parameter but not for the second.

//anExample.ExampleMethod(3,  ,4);

However, if you  know the name of the third parameter, you can use a named argument to  accomplish the task.

anExample.ExampleMethod(3, optionalint: 4);

IntelliSense uses brackets to  indicate optional parameters, as shown in the following illustration.
Optional parameters in ExampleMethod
Consider a standard scenario with method overloading or constructor chaining.  In C# we’d have several methods with different signatures where, in effect, we’re really just after default values. Let’s take the scenario where we’ve got a little helper class to send emails in our application. In some cases we want to CC the administrator to troubleshoot issues; in some cases we want rich HTML emails rather than plain text. We might set up our methods like this: 1:  public void SendMail(string toAddress, string bodyText) 2:  { 3:      this.SendMail(toAddress, bodyText, true); 4:  } 5:    6:  public void SendMail(string toAddress, string bodyText, bool ccAdministrator) 7:  { 8:      this.SendMail(toAddress, bodyText, ccAdministrator, false); 9:  } 10:    11:  public void SendMail(string toAddress, string bodyText, bool ccAdministrator, bool isBodyHtml) 12:  { 13:      // Full implementation here 14:  } This is pretty standard method overloading and we essentially are setting default values (true for CC the Admin, and false for HTML emails). With C# 4.0 we can now make the code more concise by only having to implement 1 method: 1:  public void SendMail(string toAddress, string bodyText, bool ccAdministrator = true, bool isBodyHtml = false) 2:  { 3:      // Full implementation here 4:  } However, you do have to take into account your scenario.  If you have a situation where you actually need to know if the consuming code provided a value then this isn’t a good option because if “true” comes in for the 3rd parameter, you don’t know if the consuming code actually set this explicitly or if it was simply the result of the default value.  But in typical scenarios like this, it’s not a big deal.  Cracking open Reflector and looking at the IL that the C# compiler is generating: 1:  .method public hidebysig instance void SendMail(string toAddress, string bodyText, [opt] bool ccAdministrator, [opt] bool isBodyHtml) cil managed 2:  { 3:      .param [3] = bool(true) 4:      .param [4] = bool(false) 5:      .maxstack 8 6:      L_0000: nop 7:      L_0001: ret 8:  } Which Reflectors translates to a C# equivalent of: 1:  public void SendMail(string toAddress, string bodyText, [Optional, DefaultParameterValue(true)] bool ccAdministrator, [Optional, DefaultParameterValue(false)] bool isBodyHtml) 2:  { 3:  }

How to launch a process with admin rights from a Visual Studio 2008 add-in on Windows System with UAC.

While on Windows XP by default every user is an administrator (although you can create “standard” users) Windows Vista introduces a new feature named User Account Control (UAC) which causes that by default even administrators run as standard users. When a process requires administrator rights to run, the operating system prompts for an “elevation prompt”.

Here is a demo:

System.Diagnostics.Process process = null;
System.Diagnostics.ProcessStartInfo processStartInfo;

processStartInfo = new System.Diagnostics.ProcessStartInfo();

processStartInfo.FileName = "regedit.exe";

if (System.Environment.OSVersion.Version.Major >= 6)  // Windows Vista or higher
{
   processStartInfo.Verb = "runas";
}
else
{
   // No need to prompt to run as admin
}

processStartInfo.Arguments = "";
processStartInfo.WindowStyle = System.Diagnostics.ProcessWindowStyle.Normal;
processStartInfo.UseShellExecute = true;

try
{
   process = System.Diagnostics.Process.Start(processStartInfo);
}
catch (Exception ex)
{
   MessageBox.Show(ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
finally
{
   if (process != null)
   {
      process.Dispose();
   }
}