代码之家  ›  专栏  ›  技术社区  ›  asfsadf

C自动属性-是否可以使用默认setter自定义getter?

c#
  •  8
  • asfsadf  · 技术社区  · 15 年前

    有可能我一开始就不应该尝试这个,但现在我已经做到了:

    public List<int> AuthorIDs
    {
        get
        {
            var l = new List<int>();
            using (var context = new GarbageEntities())
            {
                foreach (var author in context.Authors.Where(a => a.Books.Any(b => b.BookID == this.BookID)).ToList())
                {
                    l.Add(author.AuthorID);
                }
            }
            return l;
        }
        set; //compiler error
    }
    

    我如何让上面的setter没有任何自定义逻辑?在过去,我认为你只需要:

    set { authorIDs = value; }
    

    现在不行。

    这整个想法一开始就糟透了吗?

    编辑:

    回答一些人的问题:我正试图将MVC与数据注释验证、默认绑定、实体框架4.0……结合在一起,我相信失败得非常惊人。

    5 回复  |  直到 10 年前
        1
  •  4
  •   Michael Shimmins    15 年前

    这个答案比简单地去掉属性上的setter要宽一点——将它与其余的答案和注释结合起来,并采用有意义的部分。希望最后的一点也会有帮助,也许现在不行。

    如果您在模型中使用它进行数据绑定,因此希望将其作为属性公开,那么我会这样做:

    public class BookModel
    {
        public IList<int> AuthorIds { get; set; }
    }
    

    生成一个将调用以填充模型的服务:

    public class BookService()
    {
        public List<int> GetAuthorIDs(int bookId)
        {
            var authorIds = new List<int>();
            using (var context = new GarbageEntities())
            {
                foreach (var author in context.Authors.Where(
                    a => a.Books.Any(b => b.BookID == bookId)))
                {
                    authorIds.Add(author.AuthorID);
                }
            }
            return authorIds;
        }
    }
    

    在控制器中:

    public ViewResult List(int id)
    {
        var model = new BookModel 
        {
            AuthorIds = service.GetAuthorIDs(id)
        };
    
        return View(model);
    }
    

    我明确地没有包括如何在控制器中实例化图书服务。我的首选方案是在运行时在构造函数中注入它,但这将要求您有一个自定义控制器工厂——一次一步。您可以在默认构造函数中新建它:

    private readonly BookService service; 
    
    public BookController()
    {
        service = new BookService();
    }
    

    在一个理想的世界里,我会这样做:

    private readonly BookService service; 
    
    public BookController(BookService service)
    {
        if(service == null)
            throw new ArgumentException("service must be supplied");
    
        this.service = service;
    }
    

    但是,默认的MVC控制器工厂希望控制器具有一个默认参数,因此使用构造函数注入进行此操作将需要更多的工作。

        2
  •  7
  •   Thomas Levesque    15 年前

    不,不可能。要么一切都是明确的,要么整个属性是自动的。无论如何,在这种情况下,设置者似乎没有任何意义…根本不应该有二传手。

    另外,我认为你应该把它变成一种方法。这将使调用者更清楚地知道它执行了一个可能很长的计算。在一个属性中执行复杂处理也是违反准则的。

        3
  •  3
  •   Martin Booth    15 年前

    默认的setter将在编译时创建一个backing变量,其名称如下:

    [CompilerGenerated]
    private string <AuthorIDs>k__BackingField;
    

    因为它是在编译时创建的,所以在创建之前,不能在代码中引用它,此外,在变量名中不允许使用尖括号(故意)。

    出于这个原因,如果不允许在将来的任何时候访问这个值(毕竟这里的getter不是自动getter,它将返回一个entirel的值),那么允许在这个变量中存储某些内容(这本质上就是自动setter所做的)几乎是没有用的。Y不同)

    因此,总结一下,如果没有getter,那么(这是从这个支持变量中检索值的唯一方法)就没有必要使用私有setter

        4
  •  2
  •   roman m    15 年前

    如果您想按自己的方式来做,只需执行以下操作:

    private List<int> authorIDs;
    public List<int> AuthorIDs
    {
        get
        {
            var l = new List<int>();
            using (var context = new GarbageEntities())
            {
                foreach (var author in context.Authors.Where(a => a.Books.Any(b => b.BookID == this.BookID)).ToList())
                {
                    l.Add(author.AuthorID);
                }
            }
            return l;
        }
    
        set{authorIDs = value; //this does not make much sense though ... what are you trying to do by setting authorIDs?
    }
    }
    

    但正如其他人所说,这是对一个属性的过度杀戮,把它放在方法中,就像

    public List<int> GetAuthorIDs(int bookId)
        {
                var l = new List<int>();
                using (var context = new GarbageEntities())
                {
                    foreach (var author in context.Authors.Where(a => a.Books.Any(b => b.BookID == bookId)).ToList())
                    {
                        l.Add(author.AuthorID);
                    }
                }
                return l;
            }
    
        5
  •  0
  •   Anonymous    10 年前

    实际上有一种方法可以做到:

    public List<int> AuthorIDs
    {
        get
        {
            var l = new List<int>();
            using (var context = new GarbageEntities())
            {
                foreach (var author in context.Authors.Where(a => a.Books.Any(b => b.BookID == this.BookID)).ToList())
                {
                    l.Add(author.AuthorID);
                }
            }
            return l;
        }
        set{
           this.SetPropertyValue(page => page.AuthorIDs, value);
        }
    }