【问题标题】:Can I initialize public properties of a class using a different type in C#?我可以在 C# 中使用不同类型初始化类的公共属性吗?
【发布时间】:2015-04-04 15:37:27
【问题描述】:

在 Java 中,我可以有这样的对象:

public class MyObject {

    private Date date;

    public Date getDate() {
        return date;
    }

    public void setDate(Date date) {
        this.date = date;
    }

    public void setDate(String date) {
        this.date = parseDateString(date);
    }

    private Date parseDateString(String date) {
        // do magic here
        return dateObj;
    }

}

这很好,因为我的属性有一个 getter 和多个 setter。我可以通过传入一个 Date 对象或一个字符串来设置“日期”属性,然后让类来解决。

在 C# 中看起来有些不同。我可以这样做:

public class MyObject
{
    public DateTime Date { get; set; }
}

这里的简写显然是最佳的。但是,我不确定是否有任何内置方法可以重载 setter 以接受多种类型。我意识到我可以创建一个单独的公共方法来设置值,但这会牺牲使用对象初始化器的能力。

有没有办法直接重载 C# 的公共属性上的 setter?还是这只是语言限制,做不到?

【问题讨论】:

  • 不是答案,但我会将最新的字符串解析留在MyClass 之外。在 C# 中你只需要使用DateTime.Parse,无论如何。

标签: c#


【解决方案1】:

所有其他答案都是正确的......但是如果你坚持,你可以通过以下几种方式做到:

  1. 使用只有一个 setter 的第二个属性:

    public string DateText { set { Date = ParseDateString(value); } }
    

    尽可能避免这种情况,它只会增加混乱:-)

  2. 使用方法而不是属性(与 Java 相同)。方法可以重载。这应该是最推荐的方式。

  3. 使用自定义类(而不是 DateTime)并在 DateTimestring 和您的类之间提供隐式转换。除非您打算在其他地方使用它,否则不推荐。

  4. 将属性更改为 object 并在 setter 中提供您的转换:请不要这样做

【讨论】:

  • 我会粗体强调 如果您坚持 部分,仅设置属性在我的书中是一种代码味道...+1 以确保完整性 ;)跨度>
  • 在阅读代码时,隐式转换非常棘手。相反,您可以使用显式转换。
  • @ErnodeWeerd 我不推荐或认可这种方式,但使用显式转换有点违背“让调用者更容易”的目的,因为如果你必须转换,你也可以这样做转换(意思是:ParseDateString("1/1/1900")(MyDate)"1/1/1900" 收益并不大 :-))...但是是的,我同意,而且我个人会避免隐式转换,除非它们真的有必要并且 非常 i> clear(日期/字符串不会出现这种情况)。
  • @Jcl - 我明白了。我认为这里的问题是原始帖子中对“调用者容易”的解释过于模糊。我只是添加了评论,以防止读者认为“嘿,这很酷”,最终在尝试调试时被咬。
  • @ErnodeWeerd 100% 同意
【解决方案2】:

嗯,你是在比较苹果和香蕉。您在 Java 中拥有的内容:

public void setDate(Date date) {
    this.date = date;
}

public void setDate(String date) {
    this.date = parseDateString(date);
}

在 C# 中看起来像这样:

public void SetDate(Date date) 
{
    this.date = date;
}

public void SetDate(String date) 
{
    this.date = ParseDateString(date);
}

唯一的区别是PascalCase 成员名称和范围开括号的位置。

您的 Java 代码重载了方法;上面的 C# 有重载的方法。

AFAIK 你不能重载属性设置器,因为:

public DateTime Date 
{ 
    get { return this.date; }
    set { this.date = value; }
}

...value的类型由成员的类型决定,这里是DateTime

所以如果你想要方法重载,重载方法,而不是属性。请记住,无论如何,C# 属性只是 getter 和 setter 方法的语法糖。

【讨论】:

  • 如果 .NET 语言在看到属性集语法后会使用与他们会使用一种方法(将表达式的右侧类型作为第一个参数)。从语义上讲,如果结果与强制将值设置为属性的主要类型不同,那么语义上这样的事情会很狡猾,但是在多种类型可以相互转换的情况下,将 prop 直接设置为特定类型可能比转换然后设置。
  • @supercat 我认为这更像是一种语言/语法约束 (C#),而不是 .NET 范围内的东西。 VB.NET 确实支持参数化的 getter/setter(见鬼,VB6 做到了!)。如果我没记错的话,属性会编译为 CIL 中的 get_set_ 方法。
  • 在 VB.NET 和 C# 中,属性解析发生在系统确定对属性执行的操作之前。如果没有,可以有一个IReadableFoo<out T> 接口,它公开一个带有getter 的Foo 属性和IWritableFoo<in T>,它公开一个带有setter 的Foo,然后让IReadWriteFoo<T> 简单地继承两者。然而,由于绑定的方式,getter 和 setter 都不能作用于IReadWriteFoo<T> 类型的变量;尝试说 it.Foo=9;x=it.Foo; 将被拒绝,因为它(据说)是模棱两可的是否尝试使用...
  • ...IReadableFoo<T>.FooIWritableFoo<T>.Foo。我认为不幸的是 C# 缺少参数化索引器,因为在某些情况下,例如OrderedDictionary 的通用版本可以受益于拥有 foo.ByIndex[int]foo.ByKey[TKey] 索引属性,而不必允许 var x=foo.ByIndex;
  • @supercat 当您说“缺少参数化索引器”时-这普遍正确吗?我可以想到一些类,特别是在数据命名空间中,您可以在其中通过其 int 位置或字符串名称访问例如列集合 - docs.microsoft.com/en-us/dotnet/csharp/programming-guide/…
【解决方案3】:

自动属性不支持这一点。因此,您必须像在 Java 中那样做。

当然你也可以混合使用:提供一个自动属性和额外的设置方法来使用不同的类型设置属性。

public class MyObject 
{
    public DateTime Date { get; set; }

    public void SetDate(string date) 
    {
        this.Date = DateTime.Parse(date);
    }    
}

【讨论】:

    【解决方案4】:

    我要写一个不同的答案并声称

    public void setDate(Date date) {
        this.date = date;
    }
    
    public void setDate(String date) {
        this.date = parseDateString(date);
    }
    

    一开始是不好的做法。

    通过执行上述操作,您声称字符串和日期都是Date 的有效值。事实并非如此——您真正想要的是Date。如果用户有一个字符串并希望它转换为Date,他们应该依赖Date API 中的字符串解析功能(Java 中为DateFormat.parse(),C# 中为DateTime.Parse(),而不是你的 API。

    如果Date 是您定义的类并且您确实希望Datestring 可以互换,您应该在Date 类中使用implicit conversations,而不是询问您的@987654333 的用户@class 来写重载。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-04-12
      • 1970-01-01
      • 2011-03-22
      • 1970-01-01
      • 2017-12-02
      相关资源
      最近更新 更多