Click here to Skip to main content
13,152,454 members (40,041 online)
Click here to Skip to main content
Add your own
alternative version

Tagged as


14 bookmarked
Posted 26 Jan 2014

Determine Whether a C# Optional Parameter was Supplied

, 28 Jan 2014
Rate this:
Please Sign up or sign in to vote.
Determine whether a C# optional parameter was supplied


Using the following generic C# structure, a developer will be able to determine whether the optional argument value was supplied or default value has been chosen.


I was designing a data access layer to call database procedures. In stored procedures, we can have default parameters and my problem was to find a way to avoid passing parameters when developer chooses to use default parameter. Imagine the following Oracle stored procedure definition:

PROCEDURE GetEmployee (employeeId IN NUMBER,
   departmentName IN VARCHAR DEFAULT '%',
   departmentId IN NUMBER DEFAULT 100) AS ...

My first impression was the best way to write a mapping function is:

public Employee GetEmployee(int employeeId,
    string departmentName = "%", int departmentId = 100)
    command.Parameters.Add("employeeId", employeeId);
    command.Parameters.Add("departmentName", departmentName);
    command.Parameters.Add("departmentId", departmentId);

But this has two problems. First, you are providing something to the DbCommand which is not necessary and the second and more important problem is if a database developer changes the default value in the procedure's definition, C# is still passing the same old value which is not the default value anymore. So I thought I could solve the problem by doing something like this:

public Employee GetEmployee(int employeeId,
    string departmentName = default(string), int departmentId = default(int))
    command.Parameters.Add("employeeId", employeeId);
    if (departmentName != default(string))
    	command.Parameters.Add("departmentName", departmentName);
    if (departmentId != default(int))
        command.Parameters.Add("departmentId", departmentId);

This was a little bit better and if we don't supply value to optional parameters everything works fine as expected. But we will not be able to pass some values to the procedure using this method. In C# default(int) equals to zero and default(string) is null. So if we need to pass null for departmentName or zero for the departmentId, method body will ignore them and procedure will be executed using departmentName = '%' and departmentId = 100 instead of departmentName = NULL and departmentId = 0.

Redefining C# method using Optional<T> generic types will give us exactly what we want:

public Employee GetEmployee(int employeeId,
    Optional<string> departmentName = default(Optional<string>),
    Optional<int> departmentId = default(Optional<int>))
    command.Parameters.Add("employeeId", employeeId);
    if (departmentName.HasValue)
    	command.Parameters.Add("departmentName", departmentName.Value);
    if (departmentId.HasValue)
        command.Parameters.Add("departmentId", departmentId.Value);

This is useful especially when we want to create proxy functions like what we do in ORM libraries.

Optional<T> Structure

public struct Optional<T>
    public Optional(T value)
        _value = value;
        _hasValue = true;

    public static explicit operator T(Optional<T> optional)
        return optional._value;
    public static implicit operator Optional<T>(T value)
        return new Optional<T>(value);

    T _value;
    public T Value
        get { return _value; }
    bool _hasValue;
    public bool HasValue
        get { return _hasValue; }

    public override string ToString()
        return string.Format("Optional{ HasValue: {0}, Value: '{1}')", HasValue, Value);


void Main()
    TestFunction("required value",
        arg05: "string value",
        arg06: string.Empty,
        arg08: ConsoleColor.Red,
        arg10: 4,
        arg11: "object value",
        arg12: ConsoleColor.Blue,
        arg13: default(Optional<object>), // this is an exception and will be considered as not supplied 
        arg14: true);

public void TestFunction(
    string arg01,
    Optional<int> arg02 = default(Optional<int>),
    Optional<int> arg03 = default(Optional<int>),
    Optional<int> arg04 = default(Optional<int>),
    Optional<string> arg05 = default(Optional<string>),
    Optional<string> arg06 = default(Optional<string>),
    Optional<string> arg07 = default(Optional<string>),
    Optional<ConsoleColor> arg08 = default(Optional<ConsoleColor>),
    Optional<ConsoleColor> arg09 = default(Optional<ConsoleColor>),
    Optional<object> arg10 = default(Optional<object>),
    Optional<object> arg11 = default(Optional<object>),
    Optional<object> arg12 = default(Optional<object>),
    Optional<object> arg13 = default(Optional<object>),
    Optional<object> arg14 = default(Optional<object>),
    Optional<bool> arg15 = default(Optional<bool>))
    Console.WriteLine("// arg01: {0}", arg01);
    Console.WriteLine("// arg02: {0}", arg02);
    Console.WriteLine("// arg03: {0}", arg03);
    Console.WriteLine("// arg04: {0}", arg04);
    Console.WriteLine("// arg05: {0}", arg05);
    Console.WriteLine("// arg06: {0}", arg06);
    Console.WriteLine("// arg07: {0}", arg07);
    Console.WriteLine("// arg08: {0}", arg08);
    Console.WriteLine("// arg09: {0}", arg09);
    Console.WriteLine("// arg10: {0}", arg10);
    Console.WriteLine("// arg11: {0}", arg11);
    Console.WriteLine("// arg12: {0}", arg12);
    Console.WriteLine("// arg13: {0}", arg13);
    Console.WriteLine("// arg14: {0}", arg14);
    Console.WriteLine("// arg15: {0}", arg15);

Runtime Results

// arg01: required value
// arg02: Optional { HasValue: True, Type: [System.Int32], Value: '1234' }
// arg03: Optional { HasValue: True, Type: [System.Int32], Value: '0' }
// arg04: Optional { HasValue: False, Type: [System.Int32], Value: '0' }
// arg05: Optional { HasValue: True, Type: [System.String], Value: 'string value' }
// arg06: Optional { HasValue: True, Type: [System.String], Value: '' }
// arg07: Optional { HasValue: False, Type: [System.String], Value: '' }
// arg08: Optional { HasValue: True, Type: [System.ConsoleColor], Value: 'Red' }
// arg09: Optional { HasValue: False, Type: [System.ConsoleColor], Value: 'Black' }
// arg10: Optional { HasValue: True, Type: [System.Int32], Value: '4' }
// arg11: Optional { HasValue: True, Type: [System.String], Value: 'object value' }
// arg12: Optional { HasValue: True, Type: [System.ConsoleColor], Value: 'Blue' }
// arg13: Optional { HasValue: False, Type: [System.Object], Value: '' }
// arg14: Optional { HasValue: True, Type: [System.Boolean], Value: 'True' }
// arg15: Optional { HasValue: False, Type: [System.Boolean], Value: 'False' }


This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


About the Author

Ali Malekpour
Software Developer (Senior)
United States United States
No Biography provided

You may also be interested in...


Comments and Discussions

QuestionOption Pin
Sacha Barber26-Nov-16 11:37
mvpSacha Barber26-Nov-16 11:37 
GeneralMy vote of 5 Pin
DVL Patel9-Sep-15 23:17
professionalDVL Patel9-Sep-15 23:17 
SuggestionCorrection Pin
Richard Deeming4-Feb-14 9:22
professionalRichard Deeming4-Feb-14 9:22 
GeneralRe: Correction Pin
Ali Malekpour28-Feb-14 7:35
memberAli Malekpour28-Feb-14 7:35 
GeneralMy vote of 4 Pin
Paulo Zemek28-Jan-14 13:58
professionalPaulo Zemek28-Jan-14 13:58 
GeneralRe: My vote of 4 Pin
Ed Bouras3-Feb-14 6:37
memberEd Bouras3-Feb-14 6:37 
GeneralRe: My vote of 4 Pin
Jasmine25013-Feb-14 10:29
memberJasmine25013-Feb-14 10:29 
QuestionI am impressed. Pin
Paulo Zemek28-Jan-14 7:37
professionalPaulo Zemek28-Jan-14 7:37 
AnswerRe: I am impressed. Pin
Ali Malekpour28-Jan-14 10:59
memberAli Malekpour28-Jan-14 10:59 
QuestionI am puzzled Pin
GuyThiebaut28-Jan-14 6:07
memberGuyThiebaut28-Jan-14 6:07 
AnswerRe: I am puzzled Pin
Ali Malekpour28-Jan-14 6:50
memberAli Malekpour28-Jan-14 6:50 
GeneralRe: I am puzzled Pin
GuyThiebaut28-Jan-14 21:52
memberGuyThiebaut28-Jan-14 21:52 
AnswerRe: I am puzzled Pin
Jasmine25013-Feb-14 10:27
memberJasmine25013-Feb-14 10:27 
QuestionOK, so it's still not a problem... Pin
Dave Kreskowiak27-Jan-14 17:25
mvpDave Kreskowiak27-Jan-14 17:25 
GeneralMy vote of 3 Pin
Matt T Heffron27-Jan-14 9:35
professionalMatt T Heffron27-Jan-14 9:35 
GeneralRe: My vote of 3 Pin
Ali Malekpour27-Jan-14 16:43
memberAli Malekpour27-Jan-14 16:43 
QuestionWhat's the problem you're trying to solve? Pin
John Brett26-Jan-14 21:48
memberJohn Brett26-Jan-14 21:48 
AnswerRe: What's the problem you're trying to solve? Pin
Ali Malekpour27-Jan-14 16:40
memberAli Malekpour27-Jan-14 16:40 
GeneralRe: What's the problem you're trying to solve? Pin
John Brett28-Jan-14 1:08
memberJohn Brett28-Jan-14 1:08 
AnswerRe: What's the problem you're trying to solve? Pin
Paulo Morgado3-Feb-14 0:19
memberPaulo Morgado3-Feb-14 0:19 
QuestionWhat is the added value above default(T) and or Nullable<T> ? Pin
JV999926-Jan-14 20:33
professionalJV999926-Jan-14 20:33 
AnswerRe: What is the added value above default(T) and or Nullable<T> ? Pin
Ali Malekpour27-Jan-14 16:28
memberAli Malekpour27-Jan-14 16:28 
GeneralRe: What is the added value above default(T) and or Nullable<T> ? Pin
JV999927-Jan-14 21:06
professionalJV999927-Jan-14 21:06 
QuestionMore context needed Pin
JP van Mackelenbergh26-Jan-14 20:04
memberJP van Mackelenbergh26-Jan-14 20:04 
AnswerRe: More context needed Pin
Ali Malekpour27-Jan-14 16:32
memberAli Malekpour27-Jan-14 16:32 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

Permalink | Advertise | Privacy | Terms of Use | Mobile
Web01 | 2.8.170924.2 | Last Updated 28 Jan 2014
Article Copyright 2014 by Ali Malekpour
Everything else Copyright © CodeProject, 1999-2017
Layout: fixed | fluid