193

我最近发现了这段代码:

 public static implicit operator XElement(XmlBase xmlBase)
 {
     return xmlBase.Xml;
 }

是什么static implicit operator意思?

4

5 回答 5

320

这是一个转换运算符。这意味着您可以编写以下代码:

XmlBase myBase = new XmlBase();
XElement myElement = myBase;

编译器不会抱怨!在运行时,将执行转换运算符 -myBase作为参数传入,并返回一个有效XElement的结果。

作为开发人员,这是您告诉编译器的一种方式:

“尽管这些看起来像两种完全不相关的类型,但实际上有一种方法可以从一种转换为另一种;让我来处理如何做到这一点的逻辑。”

于 2010-11-25T04:38:04.377 回答
15

这样的隐式运算符意味着您可以隐式转换XmlBaseXElement

XmlBase xmlBase = WhatEverGetTheXmlBase();
XElement xelement = xmlBase;   
//no explicit convert here like: XElement xelement = (XElement)xmlBase;
于 2010-11-25T04:36:53.313 回答
11

另一个有趣的用法是(Unity 用来检查一个对象(以及 MonoBehavior 的一个实例)是否为空):

public static implicit operator bool (CustomClass c)
{
    return c != null;
}

请注意,代码必须在类内(在本例中为 CustomClass)。这样你就可以做这样的事情:

void Method ()
{
    CustomClass c1 = null;
    CustomClass c2 = new CustomClass ();

    bool b1 = c1; // is false
    bool b2 = c2; // is true

    if (!c1 && c2)
    {
        // Do stuff
    }
}

显然,最臭名昭著的用途可能是使用它将您的一个类转换为另一个类。但是将它们与基本类型一起使用也值得考虑......而且我很少看到它被提及。

于 2018-07-10T14:42:39.407 回答
4

它是一个隐式转换运算符(与需要(type)转换语法的显式运算符相反)

于 2010-11-25T04:37:00.813 回答
0

我的两分钱。

这在对要与 Builder Pattern 一起使用的不可变实体进行单元测试时很有用。

假设您以不可变的方式定义了 Employee 域对象。我们通常在想要遵守 DDD 风格时这样做。

public class Employee 
{ 
  public Employee(int id, string firstname, string lastname, DateTime birthdate, string street) 
  { 
    this.ID = id; 
    this.FirstName = firstname; 
    this.LastName = lastname; 
    this.BirthDate = birthdate; 
    this.Street = street; 
  } 

  public int ID { get; private set; } 
  public string FirstName { get; private set; } 
  public string LastName { get; private set; }
  public DateTime BirthDate { get; private set; } 
  public string Street { get; private set; } 

  public string getFullName() 
  { 
    return this.FirstName + " " + this.LastName; 
  } 

  public int getAge() 
  { 
    DateTime today = DateTime.Today;
    int age = today.Year - BirthDate.Year;
    
    if (BirthDate > today.AddYears(-age))
      age--;

    return age; 
  } 
}

现在您可以拥有一个如下所示的员工构建器(在测试项目内部)。注意最后,我们有这个隐式运算符。

public class EmployeeBuilder
{ 
  private int id = 1; 
  private string firstname = "first"; 
  private string lastname = "last"; 
  private DateTime birthdate = DateTime.Today; 
  private string street = "street"; 
  public Employee Build() 
  { 
    return new Employee(id, firstname, lastname, birthdate, street); 
  } 
  public EmployeeBuilder WithFirstName(string firstname) 
  { 
    this.firstname = firstname; 
    return this; 
  } 
  public EmployeeBuilder WithLastName(string lastname) 
  { 
    this.lastname = lastname; 
    return this; 
  } 
  public EmployeeBuilder WithBirthDate(DateTime birthdate) 
  { 
    this.birthdate = birthdate; 
    return this; 
  } 
  public EmployeeBuilder WithStreet(string street) 
  { 
    this.street = street; 
    return this; 
  } 
  public static implicit operator Employee(EmployeeBuilder instance) 
  { 
    return instance.Build(); 
  } 
}

现在你可以有一个像下面这样的员工测试类。

public class EmployeeTest
{
  [Test]
  public void GetFullNameReturnsCombination()
  { 
    // Arrange
    Employee emp = new EmployeeBuilder().WithFirstName("Vivek").WithLastName("Koppula"); 
    // Act
    string fullname = emp.getFullName(); 
    // Assert
    Assert.That(fullname, Is.EqualTo("Vivek Koppula")); 
  } 

  [Test] 
  public void GetAgeReturnsCorrectValue() { 
  // Arrange
  Employee emp = new EmployeeBuilder().WithBirthDate(new DateTime(1983, 1,1)); 
  // Act
  int age = emp.getAge(); 
  // Assert
  Assert.That(age, Is.EqualTo(DateTime.Today.Year - 1983)); 
  } 
}

通过使我们能够仅使用所需参数构造员工,这使得编写单元测试变得更加容易。

例如在第一个测试中,我们只关心名字和姓氏。所以对于第一种情况,我们不必为年龄和街道所困扰。

同样,对于第二种情况,我们只关心年龄而不是其他。

文章参考。

  1. 灵活且富有表现力的单元测试与构建器模式
  2. 使用测试数据的构建器模式改进测试
于 2022-01-30T07:36:53.360 回答