简体   繁体   中英

What's the theoretically fastest access to member of nullable type in C#?

I have a field of a nullable type with a value other than null . Which of the methods below is the fastest, in theory:

  1. Null conditional member access

    ThisCantBeNull?.SomeMember
  2. Cast to non-nullable

    ((MyType)ThisCantBeNull).SomeMember
  3. Use of the Value member of nullable types

    ThisCantBeNull.Value.SomeMember

Note that this is only a theoretical question, such minor differences do not matter, I'm only interested in how the language works and what goes on in the background.

Since you've already checked for null elsewhere, just get the Value , your third option.

The other two options include an extra check.

But, as noted in the comments, the performance improvement is probably minimal.

Just for curiosity:

public struct MyType
{
    public int SomeMember { get; set; }
}

Some very raw tests, disabling compiler optimizations :

MyType? thisCantBeNull = new MyType();
MyType someDefaultValue = new MyType();

var t1 = new Action(() => { var r = (thisCantBeNull ?? someDefaultValue).SomeMember; });
var t2 = new Action(() => { var r = ((MyType)thisCantBeNull).SomeMember; });
var t3 = new Action(() => { var r = thisCantBeNull.Value.SomeMember; });
var t4 = new Action(() => { var r = thisCantBeNull.GetValueOrDefault().SomeMember; });

const int times = 1000 * 1000 * 1000;

var r1 = t1.RunNTimes(times);
// Elapsed Timespan = 00:00:14.45115

var r2 = t2.RunNTimes(times);
// Elapsed Timespan = 00:00:07.9415388

var r3 = t3.RunNTimes(times);
// Elapsed Timespan = 00:00:08.0096765

var r4 = t4.RunNTimes(times);
// Elapsed Timespan = 00:00:07.4732878

The same tests, enabling compiler optimizations :

var r1 = t1.RunNTimes(times);
// Elapsed Timespan = 00:00:02.9142143

var r2 = t2.RunNTimes(times);
// Elapsed Timespan = 00:00:02.4417182

var r3 = t3.RunNTimes(times);
// Elapsed Timespan = 00:00:02.6278304

var r4 = t4.RunNTimes(times);
// Elapsed Timespan = 00:00:02.1725020

Where RunNTimes is:

public static TimeSpan RunNTimes(this Action a, int nTimes = 1)
{
    if (nTimes == 0)
        throw new ArgumentException("0 times not allowed", nameof(nTimes));

    var stopwatch = new Stopwatch();

    stopwatch.Start();
    for (int i = 0; i < nTimes; ++i)
        a();
    stopwatch.Stop();

    return stopwatch.Elapsed;;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM