Visual Studio提示私有方法内参数赋值无用该如何解决?
问题根源
你遇到的警告本质是对C#参数传递逻辑的理解偏差导致的,当前你的写法本身就无法实现「调用方法后拿到两个变量新值」的需求,VS的提示是准确的:
C#所有参数默认按值传递:
long?属于值类型,形参是外部变量的完全副本,方法内对形参的赋值只会修改副本,不会影响外部变量ProductResponse属于引用类型,默认传递的是对象引用的副本,你如果修改对象的属性外部可以感知,但直接给形参本身赋值(让形参指向新的对象),修改的只是副本存储的地址,不会改变外部变量的指向
你当前方法内对两个参数的赋值结果在方法执行完成后就会被丢弃,完全不会回传到调用方。
解决方案
方案1:使用值元组返回结果(最推荐)
C# 7+ 支持值元组作为返回值,逻辑清晰无副作用,也不需要额外定义类型,同时可以删掉无用的变量初始化代码:
修改方法定义
// 方法返回值封装需要带出的两个结果,移除原来的两个输出参数 private async Task<(long? productIdentificationRecordId, ProductResponse identificationResults)> SetProductStatusAndPerformDbActions( Company productCompany, long userId, ProductType productType, ProductStatus status, CancellationToken cancellationToken) { status = GetCompanyProductStatus(productCompany.Id, identificationResults); var recordId = await PerformDbAction(status, productType, userId, cancellationToken); var results = await IdentifyCompanyProduct(productCompany, cancellationToken); // 返回两个结果 return (recordId, results); }
调用方法
// 直接解构元组接收结果,不需要提前初始化无用的默认值 var (productIdentificationRecordId, identificationResults) = await SetProductStatusAndPerformDbActions( productCompany, userId, productType, status, cancellationToken);
方案2:使用ref关键字按引用传递参数
异步方法不支持out参数,如果需要通过参数回传结果,可以给要修改的参数加上ref关键字,此时形参会指向外部变量的内存地址,方法内的赋值会直接修改外部变量:
修改方法定义
private async Task SetProductStatusAndPerformDbActions( Company productCompany, long userId, ProductType productType, ProductStatus status, ref long? productIdentificationRecordId, // 加ref关键字 ref ProductResponse identificationResults, // 加ref关键字 CancellationToken cancellationToken) { status = GetCompanyProductStatus(productCompany.Id, identificationResults); productIdentificationRecordId = await PerformDbAction(status, productType, userId, cancellationToken); identificationResults = await IdentifyCompanyProduct(productCompany, cancellationToken); }
调用方法
long? productIdentificationRecordId = null; ProductResponse identificationResults = null; // 调用时也要加ref关键字 await SetProductStatusAndPerformDbActions( productCompany, userId, productType, status, ref productIdentificationRecordId, ref identificationResults, cancellationToken);
该方案的缺点是带ref的参数会增加理解成本,方法存在隐式副作用,调用时容易漏加ref关键字。
方案3:封装结果类
如果两个参数是关联的业务属性,可以封装成独立的结果类,方法内修改类的属性即可生效,不需要修改参数传递方式:
定义结果类
public class ProductIdentifyResult { public long? RecordId { get; set; } public ProductResponse Response { get; set; } }
修改方法定义
private async Task SetProductStatusAndPerformDbActions( Company productCompany, long userId, ProductType productType, ProductStatus status, ProductIdentifyResult result, // 传入结果类实例 CancellationToken cancellationToken) { status = GetCompanyProductStatus(productCompany.Id, result.Response); result.RecordId = await PerformDbAction(status, productType, userId, cancellationToken); result.Response = await IdentifyCompanyProduct(productCompany, cancellationToken); }
调用方法
var result = new ProductIdentifyResult(); await SetProductStatusAndPerformDbActions( productCompany, userId, productType, status, result, cancellationToken); // 后续直接使用result.RecordId、result.Response即可
该方案适合两个参数需要多次关联传递的复杂业务场景。
内容的提问来源于stack exchange,提问作者Roxy'Pro
相关产品推荐
相关产品推荐

