Return multiple values to a method caller

This is a code sample for returning multiple values from a c# method. For example, imagine a method that accepts multiple parameters and return two parameters;

So far the best method that I have found is this;

public Tuple<int, int> GetMultipleValue()
{
     return Tuple.Create(1,2);
}

This works in .NET 4 and up. Tuples with two values have Item1 and Item2 as properties.

Here is a list of different methods;

1. ref / out parameters

using ref:

static void Main(string[] args)
{
    int a = 10;
    int b = 20;
    int add = 0;
    int multiply = 0;
    Add_Multiply(a, b, ref add, ref multiply);
    Console.WriteLine(add);
    Console.WriteLine(multiply);
}

private static void Add_Multiply(int a, int b, ref int add, ref int multiply)
{
    add = a + b;
    multiply = a * b;
}

using out:

static void Main(string[] args)
{
    int a = 10;
    int b = 20;
    int add;
    int multiply;
    Add_Multiply(a, b, out add, out multiply);
    Console.WriteLine(add);
    Console.WriteLine(multiply);
}

private static void Add_Multiply(int a, int b, out int add, out int multiply)
{
    add = a + b;
    multiply = a * b;
}

2. struct / class

struct Result
{
    public int add;
    public int multiply;
}
static void Main(string[] args)
{
    int a = 10;
    int b = 20;
    var result = Add_Multiply(a, b);
    Console.WriteLine(result.add);
    Console.WriteLine(result.multiply);
}

private static Result Add_Multiply(int a, int b)
{
    var result = new Result
    {
        add = a * b,
        multiply = a + b
    };
    return result;
}

using class:

class Result
{
    public int add;
    public int multiply;
}
static void Main(string[] args)
{
    int a = 10;
    int b = 20;
    var result = Add_Multiply(a, b);
    Console.WriteLine(result.add);
    Console.WriteLine(result.multiply);
}

private static Result Add_Multiply(int a, int b)
{
    var result = new Result
    {
        add = a * b,
        multiply = a + b
    };
    return result;
}

3. Tuple

static void Main(string[] args)
{
    int a = 10;
    int b = 20;
    var result = Add_Multiply(a, b);
    Console.WriteLine(result.Item1);
    Console.WriteLine(result.Item2);
}

private static Tuple<int, int> Add_Multiply(int a, int b)
{
    var tuple = new Tuple<int, int>(a + b, a * b);
    return tuple;
}

C# 7 Tuples

static void Main(string[] args)
{
    int a = 10;
    int b = 20;
    (int a_plus_b, int a_mult_b) = Add_Multiply(a, b);
    Console.WriteLine(a_plus_b);
    Console.WriteLine(a_mult_b);
}

private static (int a_plus_b, int a_mult_b) Add_Multiply(int a, int b)
{
    return(a + b, a * b);
}

C# 7 Tuples More..

(string, string, string) LookupName(long id) // tuple return type
{
    ... // retrieve first, middle and last from data storage
    return (first, middle, last); // tuple literal
}

which could then be used like this:

var names = LookupName(id);
WriteLine($"found {names.Item1} {names.Item3}.");

You can also provide names to your elements (so they are not “Item1”, “Item2” etc). You can do it by adding a name to the signature or the return methods:

(string first, string middle, string last) LookupName(long id) // tuple elements have names

or

return (first: first, middle: middle, last: last); // named tuple elements in a literal

They can also be deconstructed, which is a pretty nice new feature:

(string first, string middle, string last) = LookupName(id1); // deconstructing declaration

Resource

https://stackoverflow.com/questions/748062/return-multiple-values-to-a-method-caller

Convert a Console App to Class Library

The big difference, you can run a console app but you can’t run a class library. Usually, Console App has Program.cs file and will compile to .exe file, a class library by default is not executable and will compile to a .dll. In .NET Core console app can also compile to DLL.

A Console App has a flow and can be executed. A Class Library is just a collection of functions that you call from another source. Class libraries by themselves are pretty useless without something to call the functions inside them.

Console App has a static MAIN method that’s an entry point. When deciding to make a method or Static class, I always keep this in mind.

A static class can be used as a convenient container for sets of methods that just operate on input parameters and do not have to get or set any internal instance fields.

Create console app. Add a greeting method. Run the app. Switch the output type to Class Libarary. Right-Click on Project -> Properties;

Before;

After;

You have best of the both worlds.

Using email template to compose and send emails

This is a simple prototype to compose and send HTML emails using a sample template.

Here is the template;

String emailTemplate = @"
<html lang=""en"">
    <head>    
        <meta content=""text/html; charset=utf-8"" http-equiv=""Content-Type"">
        <title>
            {0}
        </title>
        <style type=""text/css"">
            HTML{background-color: #e8e8e8;}
            .document-table{font-size: 12px; padding: 3px; border-collapse: collapse; border-spacing: 0;}
            .document-table .description{color: #505050;}
            .document-table td{border: 1px solid #D1D1D1; background-color: #F3F3F3; padding: 0 10px;}
            .document-table th{border: 1px solid #424242; color: #FFFFFF;text-align: left; padding: 0 10px;}
            .green{background-color: #6B9852;}
            .wrapper { margin-bottom: 20px;}
        </style>
    </head>
    <body>
        <div class=""wrapper"">
            Team,
        </div>
        <div class=""wrapper"">
            SampleDb data pull job {1} last night. The job is configured to run on {2} basis.
        </div>
        <div class=""wrapper"">
            SampleDb database is scanned between {3} for new documents. Following new document have been found and their data is copied over to the target database.
        </div>
        <div class=""wrapper"">
            <table class=""document-table"">
                <thead>
                    <tr>
                        <th class=""green"">AccountNumber</th>
                        <th class=""green"">FYQ</th>
                        <th class=""green"">DateAdded</th>
                        <th class=""green"">RowStatus</th>
                    </tr>
                </thead>
                <tbody>
                    {4}
                </tbody>
            </table>
        </div>
        <div class=""wrapper"">
            <h5><br /><br />This inbox is unattended. please do not reply to this email. This is an auto-generated message.</h5>
        </div>
    </body>
</html>
";

We can use dynamic and ExpandoObject to create data. Alternatively you can grab data from database;

var list = new List<dynamic>();
dynamic row = new ExpandoObject();
row.AccountNumber = "XYZ-100";
row.FYQ = "Q1 FY 1999";
row.DateAdded = "1999-07-28 19:38:00.000";
row.RowStatus = "processed";
list.Add(row);

We need to fill template placeholders;

StringBuilder sb = new StringBuilder();           
list.ForEach(x =>
{
   sb.Append("<tr>");
   sb.Append($"<td class='description'>{x.AwardNumber}</td>");
   sb.Append($"<td>{x.FYQ}</td>");
   sb.Append($"<td>{x.DateAdded}</td>");
   sb.Append($"<td>{x.RowStatus}</td>");
   sb.Append("</tr>");
});

replace all placeholders in HTML template;

string emailBody =
    emailTemplate.Replace("{0}", "A demo email body title")
    .Replace("{1}", "succeeded")
    .Replace("{2}", "yearly")
    .Replace("{3}", "01/01/1999 23.59.59 - 11/2/2021 02:00:00 AM")
    .Replace("{4}", sb.ToString());
               

Compose and send email out;

MailMessage mailMessage = new MailMessage();
mailMessage.From = new MailAddress("FromAdam@mail.com", "Sample Data Pull");
mailMessage.To.Add("ToJoe@mail.com");
mailMessage.Body = emailTemplate;
mailMessage.Subject = "Test email";
mailMessage.IsBodyHtml = true;
mailMessage.SubjectEncoding = Encoding.UTF8;
mailMessage.BodyEncoding = Encoding.UTF8;

//send email
using (var client = new SmtpClient("smtp-host-address"))
{
   //if true, user/pwd required, false network credentials will be used
   client.UseDefaultCredentials = true;
   if (client.UseDefaultCredentials)
   {
   client.Credentials = new NetworkCredential("FromAdmam@mail.com", "AdamSecretPassword");
   }
   client.EnableSsl = true;
   client.DeliveryMethod = SmtpDeliveryMethod.Network;
   client.Timeout = 3000;      //3 seconds
   client.Send(mailMessage);
}

Run your program and check your inbox. You will see HTML email with CSS style applied. The HTML table element is replace with our created data.

Have fun!

Dataset is empty, no tables in Dataset

This is how we can test if dataset is empty;

if(ds != null)
if(ds.Tables.Count > 0 )
if(ds.Tables[0].Rows.Count > 0)

We can loop through all tables in a method like this;

bool IsEmpty(DataSet dataSet)
{
    foreach(DataTable table in dataSet.Tables)
        if (table.Rows.Count != 0) return false;

    return true;
}

Since a DataTable could contain deleted rows RowState = Deleted, depending on what you want to achive, it could be a good idea to check the DefaultView instead (which does not contain deleted rows).

bool IsEmpty(DataSet dataSet)
{
    return !dataSet.Tables.Cast<DataTable>().Any(x => x.DefaultView.Count > 0);
}

Resource

https://stackoverflow.com/questions/2976473/how-to-test-if-a-dataset-is-empty

Dynamic type and Expando Object class

The dynamic type indicates that use of the variable and references to its members bypass compile-time type checking. Instead, these operations are resolved at run time. The dynamic type simplifies access to COM APIs such as the Office Automation APIs, to dynamic APIs such as IronPython libraries, and to the HTML Document Object Model (DOM).

Here is an example;

var list = new List<dynamic>();
dynamic row = new ExpandoObject();
row.AccountNumber = "XYZ-331";
row.FYQ = "Q3 FY 2021";
row.DateAdded = "2021-07-28 19:38:00.000";
row.RowStatus = "processed";
list.Add(row);

Here is the output;

list.ForEach(x =>
{
   Console.WriteLine($"AccountNumber = { x.AccountNumber} \nFYQ =  {x.FYQ}\nDateAdded = {x.DateAdded}\nRowStatus = {row.RowStatus}");
});

Resources

https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/builtin-types/reference-types

https://docs.microsoft.com/en-us/dotnet/api/system.dynamic.expandoobject?view=net-5.0

https://www.codegrepper.com/code-examples/csharp/add+static+data+to+list+in+c%23