Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How is this field null?

Tags:

c#

I'm getting a null exception, but the field was initialized as an empty list. So how could it be null?

The error occurs on the second line in this method (on _hydratedProperties):

protected virtual void NotifyPropertyChanged<T>(Expression<Func<T>> expression)
{
    string propertyName = GetPropertyName(expression);

    if (!this._hydratedProperties.Contains(propertyName)) { this._hydratedProperties.Add(propertyName); }
}

And this is how the field is declared:

public abstract class EntityBase<TSubclass> : INotifyPropertyChanged where TSubclass : class
{
    private List<string> _hydratedProperties = new List<string>();

This is how it's set:

    public Eta Eta
    {
        get { return this._eta; }

        set
        {
            this._eta = value;
            NotifyPropertyChanged(() => this.Eta);
        }
    }

This is the full class (with the comments and non-relevant parts removed):

[DataContract]
public abstract class EntityBase<TSubclass> : INotifyPropertyChanged where TSubclass : class
{
    private List<string> _hydratedProperties = new List<string>();

    public bool IsPropertyHydrated(string propertyName)
    {
        return this._hydratedProperties.Contains(propertyName);
    }

    public event PropertyChangedEventHandler PropertyChanged;

    protected virtual void NotifyPropertyChanged<T>(Expression<Func<T>> expression)
    {
        string propertyName = GetPropertyName(expression);

        if (!this._hydratedProperties.Contains(propertyName)) { this._hydratedProperties.Add(propertyName); }

        PropertyChangedEventHandler handler = PropertyChanged;
        if (handler != null)
        {
            handler(this, new PropertyChangedEventArgs(propertyName));
        }
    }

    public string GetPropertyName<T>(Expression<Func<T>> expression)
    {
        MemberExpression memberExpression = (MemberExpression)expression.Body;
        return memberExpression.Member.Name;
    }
}

Derived class:

[DataContract]
public class Bin : EntityBase<Bin>
{
    private Eta _eta;

    [DataMember]
    public Eta Eta
    {
        get { return this._eta; }

        set
        {
            this._eta = value;
            NotifyPropertyChanged(() => this.Eta);
        }
    }
}
like image 844
Bob Horn Avatar asked Dec 17 '15 16:12

Bob Horn


People also ask

How do you check if a field is NULL?

SELECT * FROM yourTableName WHERE yourSpecificColumnName IS NULL OR yourSpecificColumnName = ' '; The IS NULL constraint can be used whenever the column is empty and the symbol ( ' ') is used when there is empty value.

Is NULL () in SQL?

The ISNULL() function returns a specified value if the expression is NULL. If the expression is NOT NULL, this function returns the expression.

Is NULL or empty in SQL?

NULL is used in SQL to indicate that a value doesn't exist in the database. It's not to be confused with an empty string or a zero value. While NULL indicates the absence of a value, the empty string and zero both represent actual values.


2 Answers

Here's the clue:

[DataContract]

Yup. DataContractSerializer does not call any constructor. Instead, it uses FormatterServices.GetUninitializedObject to create the object that will be deserialized. This bypasses the constructor call.

Your initializer:

private List<string> _hydratedProperties = new List<string>();

is translated to an implicit default constructor by the compiler.

As a workaround, you can use a deserialization callback with OnDeserializingAttribute:

[DataContract]
public abstract class EntityBase<TSubclass> : INotifyPropertyChanged
    where TSubclass : class
{
    private List<string> _hydratedProperties;

    protected EntityBase()
    {
        Init();
    }

    private void Init()
    {
        _hydratedProperties = new List<string>()
    }

    [OnDeserializing]
    private void OnDeserializing(StreamingContext context)
    {
        Init();
    }

    // ... rest of code here
}
like image 155
Lucas Trzesniewski Avatar answered Oct 28 '22 09:10

Lucas Trzesniewski


I found a simpler answer than what Lucas provided. I'm not sure if this one is actually better, but it's simple and it worked. All I did was add the DataMember attribute to the field. Since that specifies that the field is part of the data contract, it is included with serialization/deserialization and no longer causes a null reference error.

[DataContract]
public abstract class EntityBase<TSubclass> : INotifyPropertyChanged where TSubclass : class
{
    [DataMember]
    private List<string> _hydratedProperties = new List<string>();

    // More code here
}
like image 30
Bob Horn Avatar answered Oct 28 '22 09:10

Bob Horn