dotnet / roslyn

The Roslyn .NET compiler provides C# and Visual Basic languages with rich code analysis APIs.
https://docs.microsoft.com/dotnet/csharp/roslyn-sdk/
MIT License
19.02k stars 4.03k forks source link

nameof() on collections #1380

Closed emallen closed 7 years ago

emallen commented 9 years ago

The prohibition against constructs that have the form of indexers as the operand of the nameof() operator causes some awkward workarounds to be needed in the case where the name of an item of a member of a collection is needed. I have a simplified example below:

A few noteworthy items about the example:

  1. This tends to arise in cases where an (MV*) model has a collection of submodels.
  2. I am trying to avoid having to name the type of the contained submodel (I don't want to type IItem in the Presenter code in case there is a refactoring that changes the submodel's type)
  3. The Data-Binding framework in use allows for Grid types to take a string of the form "SubmodelCollectionName.SubmodelPropertyName".

I discussed this with @BillWagner and the var shim = (true ? null : ... ); workaround construct was the best we were able to come up with as an interim solution.

using System;
using System.Collections.Generic;
using System.ComponentModel;

namespace Demo.Nameof
{
    public interface IOrder : INotifyPropertyChanged {
        int Id { get; set; }
        IList<IItem> Items { get; }
        // ...
    }

    public interface IItem : INotifyPropertyChanged {
        int Id { get; set; }
        string Name { get; }
        int Quantity { get; set; }
        // ...
    }

    public interface IControlGrid {
        void AddDataBinding(object source, params string[] propertyNames);
    }

    public interface IOrderView {
        IControlGrid ItemsGrid { get; } 
    }

    public class OrderPresenter {
        private IOrder _model;
        private IOrderView _view;

        public OrderPresenter(IOrder model, IOrderView view) {
            _model = model;
            _view = view;
            // ...
        }

        // ...

        private void Item_PropertyChanged_magicstring(object sender,
            PropertyChangedEventArgs e) {
            if (e.PropertyName == "Quantity") {
                // React to Quantity Change
            }
        }

        private void Item_PropertyChanged_nameof_workaround(object sender,
            PropertyChangedEventArgs e) {
            var shim = (true ? null : _model.Items[0]);
            if (e.PropertyName == nameof(shim.Name)) {
                // React to Quantity Change
            }
        }

        private void EstablishDataBinding_magicstring() {
            _view.ItemsGrid.AddDataBinding(_model, "Items.Name", "Items.Quantity");
        }

        private void EstablishDataBinding_nameof() {
            var shim = (true ? null : _model.Items[0]);
            _view.ItemsGrid.AddDataBinding(_model, nameof(_model.Items) + "." + nameof(shim.Name),
                nameof(_model.Items) + "." + nameof(shim.Quantity));
        }
    }
}
Przemyslaw-W commented 9 years ago

You can use type prefixed syntax - "nameof(IItem.Quantity)" and "nameof(IItem.Name)" respectively

2015-03-19 12:26 GMT+01:00 emallen notifications@github.com:

The prohibition against constructs that have the form of indexers as the operand of the nameof() operator causes some awkward workarounds to be needed in the case where the name of an item of a collection is needed. I have a simplified example below:

A few noteworthy items about the example:

  1. This tends to arise in cases where an (MV*) model has a collection of submodels.
  2. I am trying to avoid having to name the type of the contained submodel (I don't want to type IItem in the Presenter code in case there is a refactoring that changes the submodel's type)
  3. The Data-Binding framework in use allows for Grid types to take a string of the form "SubmodelCollectionName.SubmodelPropertyName".

I discussed this with @BillWagner https://github.com/BillWagner and the var shim = (true ? null : ... ); workaround construct was the best we were able to come up with as an interim solution.

using System;using System.Collections.Generic;using System.ComponentModel; namespace Demo.Nameof { public interface IOrder : INotifyPropertyChanged { int Id { get; set; } IList Items { get; } // ... }

public interface IItem : INotifyPropertyChanged {
    int Id { get; set; }
    string Name { get; }
    int Quantity { get; set; }
    // ...
}

public interface IControlGrid {
    void AddDataBinding(object source, params string[] propertyNames);
}

public interface IOrderView {
    IControlGrid ItemsGrid { get; }
}

public class OrderPresenter {
    private IOrder _model;
    private IOrderView _view;

    public OrderPresenter(IOrder model, IOrderView view) {
        _model = model;
        _view = view;
        // ...
    }

    // ...

    private void Item_PropertyChanged_magicstring(object sender,
        PropertyChangedEventArgs e) {
        if (e.PropertyName == "Quantity") {
            // React to Quantity Change
        }
    }

    private void Item_PropertyChanged_nameof_workaround(object sender,
        PropertyChangedEventArgs e) {
        var shim = (true ? null : _model.Items[0]);
        if (e.PropertyName == nameof(shim.Name)) {
            // React to Quantity Change
        }
    }

    private void EstablishDataBinding_magicstring() {
        _view.ItemsGrid.AddDataBinding(_model, "Items.Name", "Items.Quantity");
    }

    private void EstablishDataBinding_nameof() {
        var shim = (true ? null : _model.Items[0]);
        _view.ItemsGrid.AddDataBinding(_model, nameof(_model.Items) + "." + nameof(shim.Name),
            nameof(_model.Items) + "." + nameof(shim.Quantity));
    }
}

}

— Reply to this email directly or view it on GitHub https://github.com/dotnet/roslyn/issues/1380.

gafter commented 7 years ago

We are now taking language feature discussion on https://github.com/dotnet/csharplang for C# specific issues, https://github.com/dotnet/vblang for VB-specific features, and https://github.com/dotnet/csharplang for features that affect both languages.