What does the error "argument is value while parameter is declared as in" mean?
Asked Answered
S

1

5

In a netstandard 2.0 application, I have the following method that is part of a static class:

public static class Argument 
{    
    /// <param name="inst">Inst.</param>
    /// <param name="instName">Inst name.</param>
    /// <exception cref="ArgumentException">
    /// Thrown if :
    /// <paramref name="inst" /> is not specified in a local time zone.
    /// </exception>
    public static void ThrowIfIsNotLocal(in DateTime inst, string instName)
    {
        if (inst.Kind != DateTimeKind.Local)
            throw new ArgumentException(instName, $"{instName} is not expressed in a local time-zone.");
    }
}

In my program that is running .netcore 2.0, I have the following line that generates an error:

Argument.ThrowIfIsNotLocal(DateTime.Now, "timestamp");

argument is value while parameter is declared as in

Why is DateTime.Now causing the error to appear?

Sternick answered 13/8, 2018 at 21:27 Comment(2)
What type is Argument?Periscope
@Periscope This is the static class. I have added it in my question for clarity.Sternick
L
6

The method signature states that the parameter needs to be passed by reference, not by value. That means that you need to have some sort of storage location that can be referenced to pass into that method.

The result of a property getter is not a variable; it's not something that you can have a reference to. It's just a value, hence the error message.

You need to both have a variable, rather than just a value, and also use the in keyword when calling the method to indicate that you're intending to pass a reference to the variable, rather than just the value of the variable.

var now = DateTime.Now;
ThrowIfIsNotLocal(in now, "");

Of course, there's no real reason to pass this variable by reference in the first place. I'd suggest not doing so, and simply passing the parameter by value. That way callers won't need to go through all of this when they just have a value, not a variable.

Lousewort answered 13/8, 2018 at 21:40 Comment(10)
The reason of passing a struct by ref in this case is to avoid the copy and to indicate that the method does not modify the value.Sternick
Oh... Trying your solution changed the error! It now complains that readonly reference is a C# 7.2 feature. I guess I have to enable C# 7.2 in my .netcore app.Sternick
You can add the difference between in and ref keywords as in the spec (can't change the value of the passed variable inside the method)Tiphany
@Kzrystof: then how is that different from my solution. Btw, the original, with DateTime.Now seems to build as well for me. But I must say, my VS is reacting a bit strange these days.Cannabis
@Cannabis The different lies in the caller specifying the in parameter as well.Sternick
@Kzrystof Constructing the reference and passing the reference is going to be as much work as passing the value, as the size of the value is going to be no bigger than the size of the reference. If you pass it by value it also can't be changed.Lousewort
@Lousewort Looks like it is not the case :) As it can be seen in this article, the performance improvement can be significant for methods that are called often.Sternick
@Kzrystof 1) That involves a type that is much larger than a reference 2) the benchmark involves returning a value that is never used, thus the whole thing could theoretically be elided entirely. It's not a meaningful benchmark. Again, your code involves a type that is no larger than a reference, and given that the caller apparently doesn't always already have a variable, it means that they're doing a copy anyway, to put it in a variable (that wouldn't otherwise be needed) just for the purposes of this method. I didn't say it's never appropriate to use in, just that it isn't here.Lousewort
@Lousewort understood :)Sternick
@Kzrystof It's also worth nothing that the second half of that article is them talking about how hard of a time they had creating any examples that resulted in a performance difference. That should give you some idea that this isn't something you just slap on every parameter that you have, but rather something for very specific situations.Lousewort

© 2022 - 2024 — McMap. All rights reserved.