Replaces an expression in a member with a readonly field that holds an equivalent value: every constructor assigns the field from a parameter, and every construction of the class passes an equivalent expression for that parameter. Constructor Injection's recipe uses it to replace the object a method constructs with the one the class receives.
Target
Either the expression, by a selection, with arguments.field naming the field; or, in a later step of a composite, the member by symbol with:
Argument Meaning expressionthe expression as C#; every occurrence in the member is replaced fieldthe field to use in its place
Precondition
The selection is exactly one expression, or the member contains the expression. The class containing the expression declares an instance field of that name, and it is readonly, so only constructors can set it. The field's type is the expression's type. The expression is in an instance method, property, indexer or event of that class, which runs only once the object is constructed: not in a constructor, initializer, init accessor or static member. The member is not an override, which a base constructor could call before the field is assigned. The expression is a fixed value, the same wherever it is evaluated: a constant, typeof, a static readonly field, or a construction with new and no initializer whose arguments are fixed values. It reads no local, parameter or instance state and calls no method. The field has no initializer, and the class declares its constructors. Each constructor that does not call this(...) assigns the field exactly once, as a statement of its body, from a required parameter of the field's type that it never writes; it has no return statement and does not use the object before the assignment. A constructor calling this(...) does not assign the field, and no init accessor does. Every construction that runs one of those constructors, with new, target-typed new, this(...) or base(...), in any file or project, passes for the parameter an expression equivalent to the one replaced: equal constants of one type, or constructions of the same constructor with equivalent arguments, however the names in them are qualified.
The expression is replaced with the field, written this.field where a local or parameter hides it. Comments before and after the expression stay in place.
Preserved
The value the member works with: the field holds a value equivalent to the one the expression computed.
Limitations
A construction is evaluated once, when the object is constructed, rather than each time the member runs, and one object is shared by every run of the member. An object that keeps state between uses, or whose identity matters, behaves differently; this is not checked. Constants are not affected. The construction runs at the caller, before the constructor, even if the member never runs, so a constructor with side effects runs earlier. Constructions by reflection or deserialization are not seen. An expression using the class's type parameters is compared as written, so constructions of a closed type, such as new Formatter<int>() for new Formatter<T>(), are refused as different.
Error codes
Code Meaning not-an-expressionthe selection is not exactly one expression expression-not-foundthe member does not contain the expression unknown-fieldthe class declares no instance field of that name field-not-readonlythe field is not readonly type-mismatchthe field's type is not the expression's type not-in-instance-memberthe expression is not in an instance member that runs after construction not-a-fixed-valuethe expression is not built only from constants and constructions field-not-from-parametersome constructor does not assign the field once from a parameter, or something else assigns it used-during-constructionthe member could run before the field is assigned different-value-passeda construction passes a different value for the parameter
Cases
Expand all · Collapse all
Diffs show each file from before to after .
/*[*/ … /*]*/ marks a selection and /*^*/ a caret; the runner removes them before the refactoring runs.
# across-projectsA construction of the class in a project that references it is checked as well
success
Target Core/OrderService.cs, the /*[*/ … /*]*/ selection
Projects Core; App → Core
Core/OrderService.cs modified
1 1 using Shop .Mail ;2 2 3 3 namespace Shop 4 4 { 5 5 public class OrderService 6 6 { 7 7 private readonly string _prefix; 8 8 private readonly Mailer _mailer; 9 9 10 10 public OrderService (string prefix, Mailer mailer) 11 11 { 12 12 _prefix = prefix; 13 13 _mailer = mailer; 14 14 } 15 15 16 16 public void Place (string order) 17 17 { 18 18 // Mail goes out as soon as the order is placed. 19 − var mailer = /*[*/ new Mailer ("smtp.example.com" )/*]*/ ; 19 + var mailer = _mailer; 20 20 mailer.Send (_prefix + order); 21 21 } 22 22 } 23 23 }
App/Checkout.cs unchanged
1 1 namespace Shop .Web 2 2 { 3 3 public class Checkout 4 4 { 5 5 public void Complete (string order) 6 6 { 7 7 var service = new OrderService ("web-" , new Mail .Mailer ("smtp.example.com" )); 8 8 service.Place (order); 9 9 } 10 10 } 11 11 }
Core/Mailer.cs unchanged
1 1 using System .Collections .Generic ;2 2 3 3 namespace Shop .Mail 4 4 { 5 5 public class Mailer 6 6 { 7 7 private readonly string _host; 8 8 private readonly List <string > _sent = new List <string >(); 9 9 10 10 public Mailer (string host) 11 11 { 12 12 _host = host; 13 13 } 14 14 15 15 public void Send (string message) 16 16 { 17 17 _sent.Add (_host + ": " + message); 18 18 } 19 19 } 20 20 }
View fixture on GitHub
# chained-and-derived-constructionsConstructions through a chained constructor and a derived class's base call count as constructions, and pass the same construction
success
Target OrderService.cs, the /*[*/ … /*]*/ selection
OrderService.cs modified
1 1 using Shop .Mail ;2 2 3 3 namespace Shop 4 4 { 5 5 public class OrderService 6 6 { 7 7 private readonly string _prefix; 8 8 private readonly Mailer _mailer; 9 9 10 10 public OrderService () 11 11 : this ("shop-" , new Mailer ("smtp.example.com" )) 12 12 { 13 13 } 14 14 15 15 public OrderService (string prefix, Mailer mailer) 16 16 { 17 17 _prefix = prefix; 18 18 _mailer = mailer; 19 19 } 20 20 21 21 public void Place (string order) 22 22 { 23 23 // Mail goes out as soon as the order is placed. 24 − var mailer = /*[*/ new Mailer ("smtp.example.com" )/*]*/ ; 24 + var mailer = _mailer; 25 25 mailer.Send (_prefix + order); 26 26 } 27 27 } 28 28 }
Mailer.cs unchanged
1 1 using System .Collections .Generic ;2 2 3 3 namespace Shop .Mail 4 4 { 5 5 public class Mailer 6 6 { 7 7 private readonly string _host; 8 8 private readonly List <string > _sent = new List <string >(); 9 9 10 10 public Mailer (string host) 11 11 { 12 12 _host = host; 13 13 } 14 14 15 15 public void Send (string message) 16 16 { 17 17 _sent.Add (_host + ": " + message); 18 18 } 19 19 } 20 20 }
PriorityService.cs unchanged
1 1 using Shop .Mail ;2 2 3 3 namespace Shop 4 4 { 5 5 public class PriorityService : OrderService 6 6 { 7 7 public PriorityService () 8 8 : base ("vip-" , new Mailer ("smtp.example.com" )) 9 9 { 10 10 } 11 11 } 12 12 }
View fixture on GitHub
# constant-by-expressionGiven the member and the expression's text, every occurrence of a constant in the member becomes the field that every construction sets to that constant
success
Target symbol M:Paging.Paginator.Pages(System.Int32)
Arguments expression"20"field"_pageSize"
Paginator.cs modified
1 1 namespace Paging 2 2 { 3 3 public class Paginator 4 4 { 5 5 private readonly int _pageSize; 6 6 7 7 public Paginator (int pageSize) 8 8 { 9 9 _pageSize = pageSize; 10 10 } 11 11 12 12 public int Pages (int items) 13 13 { 14 − return (items + 20 - 1 ) / 20 ; 14 + return (items + _pageSize - 1 ) / _pageSize; 15 15 } 16 16 } 17 17 18 18 public class Listing 19 19 { 20 20 public int Count (int items) => new Paginator (20 ).Pages (items); 21 21 22 22 public int CountNamed (int items) => new Paginator (pageSize: 10 + 10 ).Pages (items); 23 23 } 24 24 }
View fixture on GitHub
# construction-in-methodA construction in a method becomes the readonly field every constructor assigns from a parameter, since every construction of the class, here in another namespace, passes the same construction for it
success
Target OrderService.cs, the /*[*/ … /*]*/ selection
OrderService.cs modified
1 1 using Shop .Mail ;2 2 3 3 namespace Shop 4 4 { 5 5 public class OrderService 6 6 { 7 7 private readonly string _prefix; 8 8 private readonly Mailer _mailer; 9 9 10 10 public OrderService (string prefix, Mailer mailer) 11 11 { 12 12 _prefix = prefix; 13 13 _mailer = mailer; 14 14 } 15 15 16 16 public void Place (string order) 17 17 { 18 18 // Mail goes out as soon as the order is placed. 19 − var mailer = /*[*/ new Mailer ("smtp.example.com" )/*]*/ ; 19 + var mailer = _mailer; 20 20 mailer.Send (_prefix + order); 21 21 } 22 22 } 23 23 }
Checkout.cs unchanged
1 1 namespace Shop .Web 2 2 { 3 3 public class Checkout 4 4 { 5 5 public void Complete (string order) 6 6 { 7 7 var service = new OrderService ("web-" , new Mail .Mailer ("smtp.example.com" )); 8 8 service.Place (order); 9 9 } 10 10 } 11 11 }
Mailer.cs unchanged
1 1 using System .Collections .Generic ;2 2 3 3 namespace Shop .Mail 4 4 { 5 5 public class Mailer 6 6 { 7 7 private readonly string _host; 8 8 private readonly List <string > _sent = new List <string >(); 9 9 10 10 public Mailer (string host) 11 11 { 12 12 _host = host; 13 13 } 14 14 15 15 public void Send (string message) 16 16 { 17 17 _sent.Add (_host + ": " + message); 18 18 } 19 19 } 20 20 }
View fixture on GitHub
# different-value-passed-rejectedRefuses when a construction of the class passes a different value for the parameter
refusal
Target OrderService.cs, the /*[*/ … /*]*/ selection
Refuses different-value-passed; every file is left unchanged
Checkout.cs input
1 namespace Shop .Web 2 { 3 public class Checkout 4 { 5 public void Complete (string order) 6 { 7 var service = new OrderService ("web-" , new Mail .Mailer ("smtp.other.com" )); 8 service.Place (order); 9 } 10 } 11 }
Mailer.cs input
1 using System .Collections .Generic ;2 3 namespace Shop .Mail 4 { 5 public class Mailer 6 { 7 private readonly string _host; 8 private readonly List <string > _sent = new List <string >(); 9 10 public Mailer (string host) 11 { 12 _host = host; 13 } 14 15 public void Send (string message) 16 { 17 _sent.Add (_host + ": " + message); 18 } 19 } 20 }
OrderService.cs input
1 using Shop .Mail ;2 3 namespace Shop 4 { 5 public class OrderService 6 { 7 private readonly string _prefix; 8 private readonly Mailer _mailer; 9 10 public OrderService (string prefix, Mailer mailer) 11 { 12 _prefix = prefix; 13 _mailer = mailer; 14 } 15 16 public void Place (string order) 17 { 18 // Mail goes out as soon as the order is placed. 19 var mailer = /*[*/ new Mailer ("smtp.example.com" )/*]*/ ; 20 mailer.Send (_prefix + order); 21 } 22 } 23 }
View fixture on GitHub
# expression-not-found-rejectedRefuses an expression the member does not contain
refusal
Target symbol M:Shop.OrderService.Place(System.String)
Arguments expression"new Mailer(\"smtp.other.com\")"field"_mailer"
Refuses expression-not-found; every file is left unchanged
Checkout.cs input
1 namespace Shop .Web 2 { 3 public class Checkout 4 { 5 public void Complete (string order) 6 { 7 var service = new OrderService ("web-" , new Mail .Mailer ("smtp.example.com" )); 8 service.Place (order); 9 } 10 } 11 }
Mailer.cs input
1 using System .Collections .Generic ;2 3 namespace Shop .Mail 4 { 5 public class Mailer 6 { 7 private readonly string _host; 8 private readonly List <string > _sent = new List <string >(); 9 10 public Mailer (string host) 11 { 12 _host = host; 13 } 14 15 public void Send (string message) 16 { 17 _sent.Add (_host + ": " + message); 18 } 19 } 20 }
OrderService.cs input
1 using Shop .Mail ;2 3 namespace Shop 4 { 5 public class OrderService 6 { 7 private readonly string _prefix; 8 private readonly Mailer _mailer; 9 10 public OrderService (string prefix, Mailer mailer) 11 { 12 _prefix = prefix; 13 _mailer = mailer; 14 } 15 16 public void Place (string order) 17 { 18 // Mail goes out as soon as the order is placed. 19 var mailer = /*[*/ new Mailer ("smtp.example.com" )/*]*/ ; 20 mailer.Send (_prefix + order); 21 } 22 } 23 }
View fixture on GitHub
# field-not-from-parameter-rejectedRefuses a field a constructor assigns other than from a parameter
refusal
Target OrderService.cs, the /*[*/ … /*]*/ selection
Refuses field-not-from-parameter; every file is left unchanged
Checkout.cs input
1 namespace Shop .Web 2 { 3 public class Checkout 4 { 5 public void Complete (string order) 6 { 7 var service = new OrderService ("web-" , new Mail .Mailer ("smtp.example.com" )); 8 service.Place (order); 9 } 10 } 11 }
Mailer.cs input
1 using System .Collections .Generic ;2 3 namespace Shop .Mail 4 { 5 public class Mailer 6 { 7 private readonly string _host; 8 private readonly List <string > _sent = new List <string >(); 9 10 public Mailer (string host) 11 { 12 _host = host; 13 } 14 15 public void Send (string message) 16 { 17 _sent.Add (_host + ": " + message); 18 } 19 } 20 }
OrderService.cs input
1 using Shop .Mail ;2 3 namespace Shop 4 { 5 public class OrderService 6 { 7 private readonly string _prefix; 8 private readonly Mailer _mailer; 9 10 public OrderService (string prefix, Mailer mailer) 11 { 12 _prefix = prefix; 13 _mailer = new Mailer ("smtp." + prefix); 14 } 15 16 public void Place (string order) 17 { 18 // Mail goes out as soon as the order is placed. 19 var mailer = /*[*/ new Mailer ("smtp.example.com" )/*]*/ ; 20 mailer.Send (_prefix + order); 21 } 22 } 23 }
View fixture on GitHub
# field-not-readonly-rejectedRefuses a field that is not readonly, which other code could change after construction
refusal
Target OrderService.cs, the /*[*/ … /*]*/ selection
Refuses field-not-readonly; every file is left unchanged
Checkout.cs input
1 namespace Shop .Web 2 { 3 public class Checkout 4 { 5 public void Complete (string order) 6 { 7 var service = new OrderService ("web-" , new Mail .Mailer ("smtp.example.com" )); 8 service.Place (order); 9 } 10 } 11 }
Mailer.cs input
1 using System .Collections .Generic ;2 3 namespace Shop .Mail 4 { 5 public class Mailer 6 { 7 private readonly string _host; 8 private readonly List <string > _sent = new List <string >(); 9 10 public Mailer (string host) 11 { 12 _host = host; 13 } 14 15 public void Send (string message) 16 { 17 _sent.Add (_host + ": " + message); 18 } 19 } 20 }
OrderService.cs input
1 using Shop .Mail ;2 3 namespace Shop 4 { 5 public class OrderService 6 { 7 private readonly string _prefix; 8 private Mailer _mailer; 9 10 public OrderService (string prefix, Mailer mailer) 11 { 12 _prefix = prefix; 13 _mailer = mailer; 14 } 15 16 public void Place (string order) 17 { 18 // Mail goes out as soon as the order is placed. 19 var mailer = /*[*/ new Mailer ("smtp.example.com" )/*]*/ ; 20 mailer.Send (_prefix + order); 21 } 22 } 23 }
View fixture on GitHub
# field-shadowed-by-localA field whose name a local in the method shares is qualified with this
success
Target OrderService.cs, the /*[*/ … /*]*/ selection
OrderService.cs modified
1 1 using Shop .Mail ;2 2 3 3 namespace Shop 4 4 { 5 5 public class OrderService 6 6 { 7 7 private readonly string _prefix; 8 8 private readonly Mailer mailer; 9 9 10 10 public OrderService (string prefix, Mailer mailer) 11 11 { 12 12 _prefix = prefix; 13 13 this .mailer = mailer; 14 14 } 15 15 16 16 public void Place (string order) 17 17 { 18 18 // Mail goes out as soon as the order is placed. 19 − var mailer = /*[*/ new Mailer ("smtp.example.com" )/*]*/ ; 19 + var mailer = this .mailer; 20 20 mailer.Send (_prefix + order); 21 21 } 22 22 } 23 23 }
Checkout.cs unchanged
1 1 namespace Shop .Web 2 2 { 3 3 public class Checkout 4 4 { 5 5 public void Complete (string order) 6 6 { 7 7 var service = new OrderService ("web-" , new Mail .Mailer ("smtp.example.com" )); 8 8 service.Place (order); 9 9 } 10 10 } 11 11 }
Mailer.cs unchanged
1 1 using System .Collections .Generic ;2 2 3 3 namespace Shop .Mail 4 4 { 5 5 public class Mailer 6 6 { 7 7 private readonly string _host; 8 8 private readonly List <string > _sent = new List <string >(); 9 9 10 10 public Mailer (string host) 11 11 { 12 12 _host = host; 13 13 } 14 14 15 15 public void Send (string message) 16 16 { 17 17 _sent.Add (_host + ": " + message); 18 18 } 19 19 } 20 20 }
View fixture on GitHub
# not-a-fixed-value-rejectedRefuses an expression that reads a parameter, whose value a constructor could not have been given
refusal
Target OrderService.cs, the /*[*/ … /*]*/ selection
Refuses not-a-fixed-value; every file is left unchanged
Checkout.cs input
1 namespace Shop .Web 2 { 3 public class Checkout 4 { 5 public void Complete (string order) 6 { 7 var service = new OrderService ("web-" , new Mail .Mailer ("smtp.example.com" )); 8 service.Place (order); 9 } 10 } 11 }
Mailer.cs input
1 using System .Collections .Generic ;2 3 namespace Shop .Mail 4 { 5 public class Mailer 6 { 7 private readonly string _host; 8 private readonly List <string > _sent = new List <string >(); 9 10 public Mailer (string host) 11 { 12 _host = host; 13 } 14 15 public void Send (string message) 16 { 17 _sent.Add (_host + ": " + message); 18 } 19 } 20 }
OrderService.cs input
1 using Shop .Mail ;2 3 namespace Shop 4 { 5 public class OrderService 6 { 7 private readonly string _prefix; 8 private readonly Mailer _mailer; 9 10 public OrderService (string prefix, Mailer mailer) 11 { 12 _prefix = prefix; 13 _mailer = mailer; 14 } 15 16 public void Place (string order) 17 { 18 // Mail goes out as soon as the order is placed. 19 var mailer = /*[*/ new Mailer (order)/*]*/ ; 20 mailer.Send (_prefix + order); 21 } 22 } 23 }
View fixture on GitHub
# not-an-expression-rejectedRefuses a selection that is a statement rather than an expression
refusal
Target OrderService.cs, the /*[*/ … /*]*/ selection
Refuses not-an-expression; every file is left unchanged
Checkout.cs input
1 namespace Shop .Web 2 { 3 public class Checkout 4 { 5 public void Complete (string order) 6 { 7 var service = new OrderService ("web-" , new Mail .Mailer ("smtp.example.com" )); 8 service.Place (order); 9 } 10 } 11 }
Mailer.cs input
1 using System .Collections .Generic ;2 3 namespace Shop .Mail 4 { 5 public class Mailer 6 { 7 private readonly string _host; 8 private readonly List <string > _sent = new List <string >(); 9 10 public Mailer (string host) 11 { 12 _host = host; 13 } 14 15 public void Send (string message) 16 { 17 _sent.Add (_host + ": " + message); 18 } 19 } 20 }
OrderService.cs input
1 using Shop .Mail ;2 3 namespace Shop 4 { 5 public class OrderService 6 { 7 private readonly string _prefix; 8 private readonly Mailer _mailer; 9 10 public OrderService (string prefix, Mailer mailer) 11 { 12 _prefix = prefix; 13 _mailer = mailer; 14 } 15 16 public void Place (string order) 17 { 18 // Mail goes out as soon as the order is placed. 19 /*[*/ var mailer = new Mailer ("smtp.example.com" );/*]*/ 20 mailer.Send (_prefix + order); 21 } 22 } 23 }
View fixture on GitHub
# nullable-enabledWith nullable reference types enabled, a non-nullable field assigned in the constructor replaces the construction
success
Target OrderService.cs, the /*[*/ … /*]*/ selection
Project nullable enable
OrderService.cs modified
1 1 using Shop .Mail ;2 2 3 3 namespace Shop 4 4 { 5 5 public class OrderService 6 6 { 7 7 private readonly string _prefix; 8 8 private readonly Mailer _mailer; 9 9 10 10 public OrderService (string prefix, Mailer mailer) 11 11 { 12 12 _prefix = prefix; 13 13 _mailer = mailer; 14 14 } 15 15 16 16 public void Place (string order) 17 17 { 18 18 // Mail goes out as soon as the order is placed. 19 − var mailer = /*[*/ new Mailer ("smtp.example.com" )/*]*/ ; 19 + var mailer = _mailer; 20 20 mailer.Send (_prefix + order); 21 21 } 22 22 } 23 23 }
Checkout.cs unchanged
1 1 namespace Shop .Web 2 2 { 3 3 public class Checkout 4 4 { 5 5 public void Complete (string order) 6 6 { 7 7 var service = new OrderService ("web-" , new Mail .Mailer ("smtp.example.com" )); 8 8 service.Place (order); 9 9 } 10 10 } 11 11 }
Mailer.cs unchanged
1 1 using System .Collections .Generic ;2 2 3 3 namespace Shop .Mail 4 4 { 5 5 public class Mailer 6 6 { 7 7 private readonly string _host; 8 8 private readonly List <string > _sent = new List <string >(); 9 9 10 10 public Mailer (string host) 11 11 { 12 12 _host = host; 13 13 } 14 14 15 15 public void Send (string message) 16 16 { 17 17 _sent.Add (_host + ": " + message); 18 18 } 19 19 } 20 20 }
View fixture on GitHub
# static-method-rejectedRefuses an expression in a static method, which has no object whose field it could read
refusal
Target OrderService.cs, the /*[*/ … /*]*/ selection
Refuses not-in-instance-member; every file is left unchanged
Checkout.cs input
1 namespace Shop .Web 2 { 3 public class Checkout 4 { 5 public void Complete (string order) 6 { 7 var service = new OrderService ("web-" , new Mail .Mailer ("smtp.example.com" )); 8 service.Place (order); 9 } 10 } 11 }
Mailer.cs input
1 using System .Collections .Generic ;2 3 namespace Shop .Mail 4 { 5 public class Mailer 6 { 7 private readonly string _host; 8 private readonly List <string > _sent = new List <string >(); 9 10 public Mailer (string host) 11 { 12 _host = host; 13 } 14 15 public void Send (string message) 16 { 17 _sent.Add (_host + ": " + message); 18 } 19 } 20 }
OrderService.cs input
1 using Shop .Mail ;2 3 namespace Shop 4 { 5 public class OrderService 6 { 7 private readonly string _prefix; 8 private readonly Mailer _mailer; 9 10 public OrderService (string prefix, Mailer mailer) 11 { 12 _prefix = prefix; 13 _mailer = mailer; 14 } 15 16 public void Place (string order) 17 { 18 DefaultMailer ().Send (_prefix + order); 19 } 20 21 public static Mailer DefaultMailer () 22 { 23 return /*[*/ new Mailer ("smtp.example.com" )/*]*/ ; 24 } 25 } 26 }
View fixture on GitHub
# type-mismatch-rejectedRefuses a field of another type than the expression
refusal
Target OrderService.cs, the /*[*/ … /*]*/ selection
Refuses type-mismatch; every file is left unchanged
Checkout.cs input
1 namespace Shop .Web 2 { 3 public class Checkout 4 { 5 public void Complete (string order) 6 { 7 var service = new OrderService ("web-" , new Mail .Mailer ("smtp.example.com" )); 8 service.Place (order); 9 } 10 } 11 }
Mailer.cs input
1 using System .Collections .Generic ;2 3 namespace Shop .Mail 4 { 5 public class Mailer 6 { 7 private readonly string _host; 8 private readonly List <string > _sent = new List <string >(); 9 10 public Mailer (string host) 11 { 12 _host = host; 13 } 14 15 public void Send (string message) 16 { 17 _sent.Add (_host + ": " + message); 18 } 19 } 20 }
OrderService.cs input
1 using Shop .Mail ;2 3 namespace Shop 4 { 5 public class OrderService 6 { 7 private readonly string _prefix; 8 private readonly object _mailer; 9 10 public OrderService (string prefix, Mailer mailer) 11 { 12 _prefix = prefix; 13 _mailer = mailer; 14 } 15 16 public void Place (string order) 17 { 18 // Mail goes out as soon as the order is placed. 19 var mailer = /*[*/ new Mailer ("smtp.example.com" )/*]*/ ; 20 mailer.Send (_prefix + order); 21 } 22 } 23 }
View fixture on GitHub
# unknown-field-rejectedRefuses a field the class does not declare
refusal
Target OrderService.cs, the /*[*/ … /*]*/ selection
Refuses unknown-field mentioning “'_sender'”; every file is left unchanged
Checkout.cs input
1 namespace Shop .Web 2 { 3 public class Checkout 4 { 5 public void Complete (string order) 6 { 7 var service = new OrderService ("web-" , new Mail .Mailer ("smtp.example.com" )); 8 service.Place (order); 9 } 10 } 11 }
Mailer.cs input
1 using System .Collections .Generic ;2 3 namespace Shop .Mail 4 { 5 public class Mailer 6 { 7 private readonly string _host; 8 private readonly List <string > _sent = new List <string >(); 9 10 public Mailer (string host) 11 { 12 _host = host; 13 } 14 15 public void Send (string message) 16 { 17 _sent.Add (_host + ": " + message); 18 } 19 } 20 }
OrderService.cs input
1 using Shop .Mail ;2 3 namespace Shop 4 { 5 public class OrderService 6 { 7 private readonly string _prefix; 8 private readonly Mailer _mailer; 9 10 public OrderService (string prefix, Mailer mailer) 11 { 12 _prefix = prefix; 13 _mailer = mailer; 14 } 15 16 public void Place (string order) 17 { 18 // Mail goes out as soon as the order is placed. 19 var mailer = /*[*/ new Mailer ("smtp.example.com" )/*]*/ ; 20 mailer.Send (_prefix + order); 21 } 22 } 23 }
View fixture on GitHub
# used-during-construction-rejectedRefuses when a constructor calls the member before assigning the field, when the field would still be null
refusal
Target OrderService.cs, the /*[*/ … /*]*/ selection
Refuses used-during-construction; every file is left unchanged
Checkout.cs input
1 namespace Shop .Web 2 { 3 public class Checkout 4 { 5 public void Complete (string order) 6 { 7 var service = new OrderService ("web-" , new Mail .Mailer ("smtp.example.com" )); 8 service.Place (order); 9 } 10 } 11 }
Mailer.cs input
1 using System .Collections .Generic ;2 3 namespace Shop .Mail 4 { 5 public class Mailer 6 { 7 private readonly string _host; 8 private readonly List <string > _sent = new List <string >(); 9 10 public Mailer (string host) 11 { 12 _host = host; 13 } 14 15 public void Send (string message) 16 { 17 _sent.Add (_host + ": " + message); 18 } 19 } 20 }
OrderService.cs input
1 using Shop .Mail ;2 3 namespace Shop 4 { 5 public class OrderService 6 { 7 private readonly string _prefix; 8 private readonly Mailer _mailer; 9 10 public OrderService (string prefix, Mailer mailer) 11 { 12 _prefix = prefix; 13 Place ("opening" ); 14 _mailer = mailer; 15 } 16 17 public void Place (string order) 18 { 19 // Mail goes out as soon as the order is placed. 20 var mailer = /*[*/ new Mailer ("smtp.example.com" )/*]*/ ; 21 mailer.Send (_prefix + order); 22 } 23 } 24 }
View fixture on GitHub