Bry*_*yan 2 c# extension-methods
我有一个看起来像这样的产品类 -
public class Product
{
public int ProductId { get; set; }
public string Name { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
我有一个看起来像这样的扩展类
public static class ProductExtension
{
public static void FixProduct(this Product product)
{
product = new Product(){Name = product.Name.ToUpper()};
//product.Name is now UPPERCASE
}
}
Run Code Online (Sandbox Code Playgroud)
在我的主要方法中,我有 -
static void Main(string[] args)
{
Product p = new Product() {ProductId = 1, Name = "steve"};
p.FixProduct();
System.Console.WriteLine(p.Name);
}
Run Code Online (Sandbox Code Playgroud)
这打印"steve"而不是我想要打印的内容:"STEVE".为什么扩展方法中的赋值不起作用?
我建议进行一些小改动,以遵循流畅的界面模式.而不是void返回新产品.不要使用ref,这很奇怪.
public static class ProductExtension
{
public static Product FixProduct(this Product input)
{
return new Product
{
Name = input.Name.ToUpper(),
Id = input.Id
}
//product.Name is now UPPERCASE
}
}
Run Code Online (Sandbox Code Playgroud)
然后像这样使用它:
static void Main(string[] args)
{
var p = new Product()
{
ProductId = 1,
Name = "steve"
}
.FixProduct();
System.Console.WriteLine(p.Name);
}
Run Code Online (Sandbox Code Playgroud)
这种方法的一个优点是(如果您认为您将需要它),您可以支持多个产品类,同时保留其精确类型,例如:
public static class ProductExtension
{
public static T FixProduct<T>(this T input) where T: Product, new
{
return new T
{
Name = input.Name.ToUpper(),
Id = input.Id
}
}
}
Run Code Online (Sandbox Code Playgroud)
现在,您可以在任何派生产品类上使用它,同时保持完全相同的语法.
class DeluxeProduct : Product
{ }
static void Main()
{
var p = new DeluxeProduct
{
Id = 1,
Name = "Steve"
}
.FixProduct();
Console.WriteLine(p.GetType().Name)); //outputs "DeluxeProduct"
}
Run Code Online (Sandbox Code Playgroud)
另一方面,如果您想要做的只是"修复"产品的名称,您可以将其包装在属性中.
class Product
{
private string _name;
public int Id { get; set; }
public string Name
{
get { return _name; }
set { _name = value.ToUpper(); } //Automatically "fix" it the moment you set it
}
}
Run Code Online (Sandbox Code Playgroud)
...然后你根本不需要扩展方法.
扩展方法不能以这种方式使用.在您的方法中,您创建一个新实例,Product然后将其分配给product传递对象的本地引用,而不是原始引用p.
当您第一次进入该函数时,您所拥有的是引用内存中相同对象的两个引用.
然后在退出方法之前,您有两个对象,一个由每个引用引用,带有product引用,引用在方法调用结束时由GC清理的局部变量.
解决方案:
要更正此问题并使其与您尝试执行的操作最接近,请更改方法以获取ref参数:
public static void FixProduct(ref Product product)
{
product = new Product() { Name = product.Name.ToUpper() };
//product.Name is now UPPERCASE
}
Run Code Online (Sandbox Code Playgroud)
然后:
ProductExtension.FixProduct(ref p);
Run Code Online (Sandbox Code Playgroud)我相信一个更好的方法将(通过使用成员函数或扩展方法)更新对象而不是实例化新对象:
public static void FixProduct(this Product product)
{
product.Name = product.Name.ToUpper();
}
Run Code Online (Sandbox Code Playgroud)