Releases: linkdotnet/IfItQuacks
Release list
v1.3.0
Added
-
[DuckTyped]extension methods: the receiver is duck-typed too, soperson.Greet()works for any type fitting the interface. Previously reported withIFITQUACKS004. -
A public property or field of a delegate type satisfies an interface method of the same name, which makes an object literal a test double:
Duck.As<IRepository>(new { Find = (Func<int, Order?>)(id => ...) }). -
Duck.Stub<TShape>(value)andDuck.Stub<TShape>()return a test double that forwards the members the value provides and throwsDuckStubExceptionfor the rest. A member that is present but doesn't fit is still reported withIFITQUACKS001. -
Duck.Merge<TShape>(first, second)(and a three-value overload) builds one interface from several values, taking each member from the first value providing it - a spy or a partial fake without a mocking library. -
Sequences are adapted element by element:
IEnumerable<T>,IReadOnlyCollection<T>andIReadOnlyList<T>parameters accept aList<Person>or aPerson[]whose elements fit, andDuck.As<IReadOnlyList<INamed>>(people)keepsCountand the indexer. -
Duck.To<TTarget>(value)copies a value into a new one of a concrete type, filling the constructor and the remaining settable members from the members of the same name. DiagnosticIFITQUACKS009. -
Samples:
IfItQuacks.Sample.Extensions,IfItQuacks.Sample.Sequences,IfItQuacks.Sample.TestingandIfItQuacks.Sample.Copying.
Fixed
-
greeter?.Greet(duck)is intercepted. A conditional access used to fall through to the runtime fallback and throwDuckTypeMismatchExceptionalthough the call was right there in the project. -
base.Greet(duck)no longer silently calls the overriding method. Abasecall is not virtual, which neither an interceptor nor the fallback overload can reproduce, so it is reported with the newIFITQUACKS008. -
An argument typed as
Person?shares the adapter generated forPersoninstead of getting a second one whose generated code warned about a possible null dereference.
Changed
IFITQUACKS007is titled Duck conversion target must be an interface and names the conversion (Duck.As,Duck.StuborDuck.Merge) that was called.
v1.2.0
Added
-
Delegates, lambdas and method groups satisfy an interface with a single method (a functional interface), both as
[DuckTyped]arguments and throughDuck.As. -
A
[DuckTyped]method converts to a delegate over the duck type (Func<Person, string> f = Ops.Describe;,items.Select(Ops.Describe)) through a generated overload. -
static abstractmembers and operators via duck-typed constraints (where T : IAddable<T>), including BCL generic math interfaces such asIAdditionOperators<T, T, T>. The generated adapter is its own type argument, so these calls don't box. -
Samples:
IfItQuacks.Sample.DelegatesandIfItQuacks.Sample.GenericMath. -
Documentation: a Benchmarks page with measured numbers (BenchmarkDotNet,
MemoryDiagnoser) for duck-typed calls and forDuck.Asused as a view instead of a mapper. -
Samples:
IfItQuacks.Sample.Members(events, indexers,refreturns, default interface members) andIfItQuacks.Sample.Signatures(ref/out/paramsparameters,privatemethods, methods on a struct, runtime fallback).
Changed
- Documentation: Known limitations is grouped into fewer sections, each showing the code that doesn't work.
Fixed
IFITQUACKS005no longer mentionsrefreturns, which are supported now, and its title matches the documentation.- Interface properties and indexers with an
initsetter are adapted correctly. A type whose setter isinit-only is reported as a mismatch instead of producing invalid code. [DuckTyped]methods in an interface or in afile-local type are reported withIFITQUACKS004instead of silently generating code for a different type.readonlyandrefstruct containing types keep their modifiers.- Members inherited from base interfaces are found when the argument is statically typed as an interface.
- A member of the argument's type that hides the inherited member the interface was matched against no longer breaks the generated adapter.
- Type argument inference skips static and generic candidate members and honours
refreturns, matching the rules used for structural matching.
v1.1.0
Added
[DuckTyped]instance methods on structs. The receiver is passed by reference, so mutations reach the caller's value.private,protectedandprivate protected[DuckTyped]methods.- Interface members returning by
reforref readonly(methods, properties and indexers) can be adapted if the matching member returns the same type by reference.
v1.0.0
Added
[DuckTyped]attribute for compile-time checked structural typing of interface parameters via generated adapters and interceptors. Any interface works, no attribute on the interface needed.- Diagnostics
IFITQUACKS001-IFITQUACKS006. - Generic interfaces and generic
[DuckTyped]methods, with type arguments inferred per argument type. Duck.As<TShape>(value)to convert a value explicitly, e.g. to store it in a field or collection. DiagnosticIFITQUACKS007.[DuckTyped]instance methods and methods with several parameters, including multiple interface parameters,ref/out,params, default values and named arguments.- Interfaces with events, indexers and default interface members. Unsupported interface members are reported with
IFITQUACKS005. - Framework interfaces like
IDisposableandIEnumerable<T>; types implementing an interface (also explicitly or through variance) are passed through without an adapter. - Interface parameters accept
null,defaultand omitted default values. - Calls that can't be verified at compile time (e.g. from generic code) work at runtime if the value implements the interface, otherwise
DuckTypeMismatchExceptionis thrown. - Generated types are
internal, so several projects in a solution can use IfItQuacks. - Generated overloads are hidden from IntelliSense.
- The generator is incremental and only re-analyzes calls to
[DuckTyped]methods andDuck.As. - The package enables
InterceptorsNamespacesforIfItQuacks.Generated, so no project file changes are needed. - Member types only need to be assignable (covariant returns and getters, contravariant parameters and setters,
voidinterface methods discard results) instead of identical. - Public fields satisfy interface properties.
- Anonymous types can be passed to
[DuckTyped]methods andDuck.As. - Adapters forward
Equals,GetHashCodeandToStringto the wrapped instance;Duck.Unwrapreturns it.