0

IListModel exposes a generic list property called Items of abstract type ListItemModel. But when I try to convert any derived class to IListModel I get "Object reference not set to an instance of an object" error.

public abstract class ListItemModel
{
    public string UserName { get; set; }
    public string SomeProperty { get; set; }
}

public interface IListModel<T> where T : ListItemModel
{
    List<T> Items { get; set; }
}

public class UserListModel : IListModel<UserListItemModel>
{
    public string Query { get; set; }
    public int TotalUsers { get; set; }

    public List<UserListItemModel> Items { get; set; }
}

public class UserListItemModel : ListItemModel
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
}

var users = new UserListModel
{
    Query = "a",
    TotalUsers = 1111,
    Items = new List<UserListItemModel>
    {
        new UserListItemModel {FirstName = "a", LastName = "b"}
    }
};

// later in the application users will be passed around as an object which 
// must cast it to  IListModel<ListItemModel> in order to access its properties
// but converted will return null
var converted = users as IListModel<ListItemModel>;


foreach (var item in converted .Items)
{
    item.SomeProperty = DoSomethingHere(item.UserName);
}

What I am trying to achieve here is being able to populate SomePropery from ListItemModel base class.

0

3 Answers 3

1

Please refer to: as (C# reference)

However, if the conversion isn't possible, as returns null instead of raising an exception.

Basically, what's happening is that you're doing an invalid cast, and the result of that invalid cast depends on the form of casting used.

var converted = users as IListModel<ListItemModel>; // converted is null
var converted = (IListModel<ListItemModel>)users;   // raises exception

Is casting actually necessary? UserListModel : IListModel<UserListItemModel> seems to indicate that it IS an IListModel of the type you want, so you should just be able to supply it into the foreach block and work from that, no?

Sign up to request clarification or add additional context in comments.

1 Comment

As I added it later in the code as a comment, users object will be passed around in the code as an object which must cast it to IListModel<ListItemModel> in order to access its properties. Also UserListModel is one of the many implementations of IListModel<ListItemModel>.
1

Create a generic list item reference interface:

public interface IListItemModel
{
    List<ListItemModel> Items { get; }
}

Have your classes implement with an explicit constructor:

List<LIstItemModel> IListModel.Items
{
  get { return this.Items; }
}

And then you can cast users to IListModel.

5 Comments

Thanks for your reply but I will get users as an object that has to be cast to IListModel<ListItemModel> in order to access its properties.
Imagine you are getting users as an object type, first you have to cast it to its base type, which is IListModel<ListItemModel>, and then you can access the Items property. Problem is that the casting fails.
This works! The only thing is that I have to add the explicit constructor to all derived classes. I wish there was a cleaner solution. But this solves my problem for now. Thanks a lot.
Explicit constructor to do what? It should just return the existing Items property collection
I could come up with a solution with the help of your answer. I posted the code as well. Thank you very much.
0

Thanks to "Brian Mains" and "Kyle Baran" my problem is solved. Here is the working code:

public abstract class ListItemModel
{
    public string UserName { get; set; }
}

public interface IListModel
{
    List<ListItemModel> ListItems { get; }
}

public abstract class BaseListModel<T> : IListModel where T : ListItemModel
{
    public List<T> Items { get; set; }

    public List<ListItemModel> ListItems
    {
        get { return Items.Cast<ListItemModel>().ToList(); }
    }
}

public class UserListModel : BaseListModel<UserListItemModel>
{
    public string Query { get; set; }
    public int TotalUsers { get; set; }
}

public class UserListItemModel : ListItemModel
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
}

var users = new UserListModel
{
    Query = "a",
    TotalUsers = 1111,
    Items = new List<UserListItemModel>
    {
        new UserListItemModel {FirstName = "a", LastName = "b"}
    }
};

// and finally I can cast the collection to IListModel
var converted = users as IListModel;


foreach (var item in converted .Items)
{
    item.SomeProperty = DoSomethingHere(item.UserName);
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.