简体   繁体   中英

var keyword can change a variable type to dynamic?

I have a service for Entity1 whose name is Entity1Service and it contains a method GetBySerial which is responsible for fetch the appropriate document from the database (I used LiteDb ) and returns it:

public class Entity1Service
{
    private readonly LiteCollection<Entity1> _entity1Collection;
    private readonly LiteDatabase _db;

    public Entity1Service()
    {
        _db = new LiteDatabase(Constants.DbFileName);
        _entity1Collection = _db.GetCollection<Entity1>(nameof(Entity1));
    }
    public Entity1 GetBySerial(string serial)
    {
        var q = Query.EQ(nameof(Entity1.Serial), serial);

        lock (Constants.DbLockObj)
        {
            return _entity1Collection.Find(q).SingleOrDefault();
        }
    }
}

If I use this method like this:

Entity1Service _entity1Service = new Entity1Service();
dynamic MyDynamic = new System.Dynamic.ExpandoObject();
MyDynamic.Serial = "serial";
var e1 = _entity1Service.GetBySerial(MyDynamic.Serial);

the e1 will be a dynamic variable. But, if I use it like this:

Entity1 e1 = _entity1Service.GetBySerial("serial");

Its type will be Entity1 as expected. I can't figure out why the compiler acts like this.

I face this behavior in a console application, dotnet core v. 2.1 and C# v. 7.3

Update:

Thanks to Jon Skeet, I tried to make a "minimal reproducible example" as he mentioned in a comment. So, during this process, I found that the problem is happened because of a code that I removed from the code for simplicity. So, the problem exactly happens when I pass a dynamic value as the argument to the method. So I edited the first code section.

This isn't really about var . That just showed up something that was already going on in your explicitly-typed code. This is about how dynamic typing works. The result of almost any expression involving dynamic is deemed to be dynamic .

So in this code:

Entity1Service _entity1Service = new Entity1Service();
dynamic MyDynamic = new System.Dynamic.ExpandoObject();
MyDynamic.Serial = "serial";
var e1 = _entity1Service.GetBySerial(MyDynamic.Serial);

... the compile-time type of MyDynamic.Serial is dynamic , and the call to _entity1Service.GetBySerial is dynamically bound, with a result of dynamic . When you explicitly type e1 as Entity1 , you're effectively adding a cast after the call.

If you just make sure everything in the expression is statically typed, the result will have the static type you expect. For example, you could cast the argument:

Entity1Service _entity1Service = new Entity1Service();
dynamic MyDynamic = new System.Dynamic.ExpandoObject();
MyDynamic.Serial = "serial";
var e1 = _entity1Service.GetBySerial((string) MyDynamic.Serial);

Or you could use a separate local variable:

Entity1Service _entity1Service = new Entity1Service();
dynamic MyDynamic = new System.Dynamic.ExpandoObject();
MyDynamic.Serial = "serial";
string serial = MyDynamic.Serial;
var e1 = _entity1Service.GetBySerial(serial);

Either way, the _entity1Service.GetBySerial call is now statically bound - which is almost certainly what you want - and the type of e1 will be Entity1 .

a brief history of var;

var was introduced in C#3.0. Its purpose is to “implicitly” tell the compiler what type of variable it is. This means that the variable type is determined by the compiler at compilation time.

dynamic keyword is more used for inter language field information. It should be discouraged. Its like an object type without the need for cast.

Without looking at the code, its hard to tell. Its more of a guess.

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