3

In my method, I have this query:

var query =
    _db.STEWARDSHIP
        .OrderBy(r => r.SITE.SITE_NAME)
        .Where(r => SiteId == null || r.SITE_ID == iSiteId)
        .Where(r => SiteTypeId == null || r.SITE.SITE_TYPE_VAL.SITE_TYPE_ID == iSiteTypeId)
        .Where(r => EcoregionId == null || r.SITE.ECOREGION_VAL.ECOREGION_ID == iEcoregionId)
        .Where(r => ConservationAreaId == null || r.SITE.CONSERVATION_AREA_VAL.CONSERVATION_AREA_ID == iConservationAreaId)
        .Where(r => VisitTypeId == null || r.VISIT_TYPE_VAL.VISIT_TYPE_ID == iVisitTypeId)
        .Where(r => Staff == null || r.STAFF.Contains(sStaff))
        .Where(r => Comment == null || r.VISIT_COMMENTS.Contains(sComment))
        .Select(r => new SiteVisitDetails
        {
            Id = r.STEWARDSHIP_ID,
            Name = r.SITE.SITE_NAME,
            VisitType = r.VISIT_TYPE_VAL.VISIT_TYPE_DESC,
            VisitDate = r.VISIT_DATE
        });

This fails with the error:

SiteVisitDetails does not contain a constructor that takes 0 arguments

Here the class:

public class SiteVisitDetails : ISiteVisitDetails
{

    private int _id;
    private string _name;
    private DateTime _visitDate;
    private string _visitType;

    public SiteVisitDetails(int Id, string Name, DateTime VisitDate, 
                            string VisitType)
    {
        _id = Id;
        _name = Name;
        _visitDate = VisitDate;
        _visitType = VisitType;
    }

    public int Id
    {
        get { return _id; }
        set { _id = value; }
    }

    public string Name
    {
        get { return _name; }
        set { _name = value; }
    }

    public DateTime VisitDate
    {
        get { return _visitDate; }
        set { _visitDate = value; }
    }

    public string VisitType
    {
        get { return _visitType; }
        set { _visitType = value; }
    }

    public string getShortVisitDate()
    { 
        return _visitDate.ToShortDateString();
    }
}

The Interface:

interface ISiteVisitDetails
{
    int Id { get; set; }
    string Name { get; set; }
    DateTime VisitDate { get; set; }
    string VisitType { get; set; }
    string getShortVisitDate;
}

I don't understand why I would need a constructor that takes 0 arguments. Can somebody help me understand?

Thanks.

  • There's a thing with C# and default constructors. structs will have their own, non-overloadable default constructors. With generics, you can construct an object of type T only with the default constructor (the "new()" clause at the end of the where statement), and all WPF I saw are constructed with that default constructor, their parameters being set after, one by one... – paercebal Nov 18 '11 at 16:08

6 Answers6

9

don't understand why I would need a constructor that takes 0 arguments.

The expression:

new SiteVisitDetails
{
    Id = r.STEWARDSHIP_ID,
    Name = r.SITE.SITE_NAME,
    VisitType = r.VISIT_TYPE_VAL.VISIT_TYPE_DESC,             
    VisitDate = r.VISIT_DATE
}

is really shorthand for:

new SiteVisitDetails() // Note the parantheses
{
    Id = r.STEWARDSHIP_ID,
    Name = r.SITE.SITE_NAME,
    VisitType = r.VISIT_TYPE_VAL.VISIT_TYPE_DESC,
    VisitDate = r.VISIT_DATE
}

From the language specification:

7.6.10.1 Object creation expressions

[...] An object creation expression can omit the constructor argument list and enclosing parentheses provided it includes an object initializer or collection initializer. Omitting the constructor argument list and enclosing parentheses is equivalent to specifying an empty argument list.

In other words, you really are trying to call the parameterless constructor of the SiteVisitDetails type, which doesn't exist of course.

Ani
  • 111,048
  • 26
  • 262
  • 307
3
Foo result = new Foo { A = 1, B = 2 };

is the same as

Foo temp = new Foo();
temp.A = 1;
temp.B = 2;
Foo result = temp;

As you can see, this involves a call to a parameterless constructor.


If you don't have a parameterless constructor, but a constructor like

public Foo(int a)

you need to use like this:

Foo result = new Foo(1) { B = 2 };

which is the same as

Foo temp = new Foo(1);
temp.B = 2;
Foo result = temp;
dtb
  • 213,145
  • 36
  • 401
  • 431
1

I believe by using the notation above where you initialize each item inside { } what really happens is that your object is created with the (inexisting) default constructor and later each property is initialized. Since the default constructor doesn't exist, you get the exception.

Otávio Décio
  • 73,752
  • 17
  • 161
  • 228
1

You are using object initializer which allows you to assign any publicly accessible fields during construction.

new SiteVisitDetails
    {
        Id = r.STEWARDSHIP_ID,
        Name = r.SITE.SITE_NAME,
        VisitType = r.VISIT_TYPE_VAL.VISIT_TYPE_DESC,
        VisitDate = r.VISIT_DATE
    });

which translates to

var s = new SiteVisitDetails();
s.Id = blah;
s.Name = blah;

so you need an empty constructor to use that code construct.

Peter Kelly
  • 14,253
  • 6
  • 54
  • 63
0

Well, you're trying to instantiate the class with 0 parameters right here:

.Select(r => new SiteVisitDetails 
Daniel Mann
  • 57,011
  • 13
  • 100
  • 120
0

You're expressly creating an instance of an object via its default constructor (with no parameters) and are then using the syntactic sugar of the braces to set properties of the object:

 .Select(r => new SiteVisitDetails 
    { 
        Id = r.STEWARDSHIP_ID, 
        Name = r.SITE.SITE_NAME, 
        VisitType = r.VISIT_TYPE_VAL.VISIT_TYPE_DESC, 
        VisitDate = r.VISIT_DATE 
    }

Try calling the specified constructor ...

public SiteVisitDetails(int Id, string Name, DateTime VisitDate, string VisitType)  

... passing the required fields and then use the class initializer to set any remaining fields you want to set:

 .Select(r => new SiteVisitDetails(         
        Id = r.STEWARDSHIP_ID, 
        Name = r.SITE.SITE_NAME, 
        VisitType = r.VISIT_TYPE_VAL.VISIT_TYPE_DESC, 
        VisitDate = r.VISIT_DATE 
    ));
Rich Turner
  • 10,800
  • 1
  • 51
  • 68