2

How to implement this in C# 4 with extensions:

string challengeId;
if(challengeId == mViewModel?.Challenge?.Id)

where Challenge.Id is string

I was given some extension:

public static TValue GetOrDefault<TObject, TValue>(this TObject obj, Func<TObject, TValue> getter, TValue defaultValue = default(TValue))
            where TObject : class
        {
            return obj == null ? defaultValue : getter(obj);
        }

then i can use it so:

string challengeId;
if(challengeId == mViewModel.GetOrDefault(x => x.Challeng).GetOrDefault(x => x.Id)

will be this ok in all combinations. What about if Id's are not string and we want to compare int?

int challengeId;
    if(challengeId == mViewModel.GetOrDefault(x => x.Challeng).GetOrDefault(x => x.Id)

where Challenge.Id is int

Community
  • 1
  • 1
mbrc
  • 3,523
  • 13
  • 40
  • 64
  • can u specify your question? When `Challenge.Id` is int and `challengeId` is a String? – jHilscher Jan 02 '16 at 08:13
  • 1
    You say *you* wrote that extension. Did you really write that yourself? It has the exact same generic type argument names, parameter names, stylitic considerations as what's available here on SO. It's possible, I guess, but it would be an amazing coincidence. –  Jan 02 '16 at 09:06
  • Anyway, `challengeId == mViewModel.GetOrDefault(x => x.Challeng).GetOrDefault(x => x.Id)` will compile, aside from the `Challeng` typo. Whether it does what you want depends on what you want. It's not clear from your question what you want. –  Jan 02 '16 at 09:09
  • If you have VS2015 you can use the new syntax in .Net 4. – Lasse V. Karlsen Jan 02 '16 at 09:22
  • 1
    Otherwise, just leave out `where TObject : class`. – Lasse V. Karlsen Jan 02 '16 at 09:26
  • @LasseV.Karlsen That's not necessary. The only value type used in the question is `TValue`, which doesn't have a `: class` constraint to remove. –  Jan 02 '16 at 09:35
  • You're right, I misread the part about the int. – Lasse V. Karlsen Jan 02 '16 at 09:36
  • 2
    By the way, [please don't delete your questions after receiving an answer](http://stackoverflow.com/questions/34483550/convert-new-c-sharp-6-features-to-c-sharp-5). It's rude towards the people that spent time trying to help you, and not how SO is supposed to work. The deal is supposed to be that in exchange for help from other SO users, you leave your questions up to benefit other SO users. –  Jan 02 '16 at 09:50
  • Oh FFS. I didn't realise that the exact same method that was available here on SO was posted as an answer to a question *of yours*. So you ask a question, get a helper method as an answer, and then claim it as your own? What's wrong with you? Why on earth would you ever think that might be an even remotely acceptable idea? –  Jan 03 '16 at 13:13

1 Answers1

4

For value types, the null conditional operator returns a nullable. You would have to create an overload specifically for value types that returns nullables.

Something like this should work:

public static TValue? GetOrDefault<TObject, TValue>(this TObject obj, Func<TObject, TValue> getter, TValue? defaultValue = default(TValue?))
    where TObject : class
    where TValue : struct
{
    return obj == null ? defaultValue : getter(obj);
}

You may need to change the name or something because the compiler might find the method ambiguous with the other overload. The compiler will not know which overload to use because the way they're used, it can't be easily distinguished.

For instance:

mViewModel.GetOrDefault(x => x.Challenge).GetOrDefault(x => x.Id)

The second use would be ambiguous because it's unclear to the compiler what overload is intended. The generic constraints is not enough to resolve the overload.

You would wither have to make which overload to use clear by specifying enough arguments that the compiler can infer which is correct, specify the type parameters, or as I suggested earlier, change the name of the method.

mViewModel.GetOrDefault(x => x.Challenge).GetOrDefault(x => x.Id, default(int?))

or

mViewModel.GetOrDefault(x => x.Challenge).GetOrDefault<Challenge, int>(x => x.Id)

or

mViewModel.GetReferenceOrDefault(x => x.Challenge).GetValueOrDefault(x => x.Id)
Jeff Mercado
  • 129,526
  • 32
  • 251
  • 272