EasyCache includes more than cache provider. Therefore seperate packages by cache provider. For Example;
EasyCache.Memory
EasyCache.Redis
EasyCache.MemCache
if you implement new provider follow name pattern. (EasyCache.{ProviderName}
)
EasyCache.Core
includes base methods for cache operation.
If the code you develop is basic for cache operations, this development should be in EasyCache.Core.
EasyCache.AspNetCore
depends AspNetCore. If the code you develop is depends AspNetCore, this development should be in EasyCache.AspNetCore
This docuemnt contains class members ordering rules. C# class member must be placed with right order to keep code qulity high!
The following ordering applies to this project:
(SA1201 & SA1203)
- Constant Fields
- Fields
- Constructors
- Finalizers (Destructors)
- Delegates
- Events
- Enums
- Interfaces (interface implementations)
- Properties
- Indexers
- Methods
- Structs
- Classes
(SA1202)
- public
- internal
- protected internal
- protected
- private
(SA1204)
- static
- non-static
(SA1214 and SA1215)
- readonly
- non-readonly
StyleCrop rules are used in this project and this document was prepared according to StyleCrop Rules Documentation
This folder includes helper codes and extensions which is undependent from any context. They are generic helper codes.
This folder includes all interfaces in project.
This folder includes all implementation in project.
Library | Description | Version |
---|---|---|
Microsoft.Extensions.DependencyInjection | Extension of Dotnet | v5.0.1 |
Library | Description | Version |
---|---|---|
Microsoft.AspNetCore.Mvc.Abstractions | Mvc Abstractions | v2.2.0 |
Microsoft.AspNetCore.Mvc.Core | ASP.NET Core is a cross-platform .NET framework for building modern cloud-based web applications on Windows, Mac, or Linux. | v2.2.5 |
Library | Description | Version |
---|---|---|
EnyimMemcachedCore | A Memcached client for .NET Core. Available on Nuget | v2.5.1 |
Library | Description | Version |
---|---|---|
Microsoft.Extensions.Caching.Memory | Extension of Dotnet | v5.0.0 |
Library | Description | Version |
---|---|---|
Microsoft.Extensions.Caching.StackExchangeRedis | Extension of Dotnet | v5.0.1 |
This document is created to guide your style of code.
First rule is:
You MUST follow .editorconfig file!
You can get .editorconfig file from here
Other rules is listed below:
Do not prefer this
// Prefer:
capacity = 0;
// Over:
this.capacity = 0;
Prefer this
// Prefer:
this.Id = 0;
// Over:
Id = 0;
Do not prefer this
// Prefer:
Display();
// Over:
this.Display();
Prefer this
.
// Prefer:
this.Elapsed += Handler;
// Over:
Elapsed += Handler;
⚠ Prefer predefined type instead of framework type.
For example use
int
instead ofInt32
private int _member;
static void M(int argument)
{
int local;
}
static void M(int argument)
{
int local = int.MaxValue;
}
Prefer explicit type
// Prefer:
int x = 5; // built-in types
// Over:
var x = 5; // built-in types
Prefer var
var cojb = new C(); //type is apparent from assignment expression
Prefer var
var f = this.Init(); //everywhere else
When on multiple lines
// Allow:
if (test) Console.WriteLine("Text");
// Allow:
if (test)
Console.WriteLine("Text");
// Prefer:
if (test)
{
Console.WriteLine("Text");
}
// Over:
if (test)
Console.WriteLine(
"Text");
⚠ Yes
// Prefer:
public int Age { get; }
// Over:
private int age;
public int Age
{
get
{
return age;
}
}
Yes
// Prefer:
void Method()
{
using var resource = GetResource();
ProcessResource(resource);
}
// Prefer:
void Method()
{
using (var resource = GetResource())
ProcessResource(resource);
}
// Over:
void Method()
{
using (var resource = GetResource())
{
ProcessResource(resource);
}
}
*
/
%
+
-
<<
>>
&
^
|
Never if unnecessary
// Prefer:
var v = a + b * c;
// Over:
var v = a + (b * c);
&&
||
??
Always for clarity
// Prefer:
var v = a || (b && c);
// Over:
var v = a || b && c;
<
>
<=
>=
is
as
!=
Always for clarity
// Prefer:
var v = (a < b) == (c > b);
// Over:
var v = a < b == c > b;
Never if unnecessary
// Prefer:
var v = a.b.Length;
// Over:
var v = (a.b).Length;
⚠ Yes
// Prefer:
var c = new Customer
{
Age = 21
};
// Over:
var c = new Customer();
c.Age = 21;
⚠ Yes
// Prefer:
var list = new List<int>
{
1,
2,
3,
};
// Over:
var list = new List<int>();
list.Add(1);
list.Add(2);
list.Add(3);
⚠ Yes
// Prefer:
if (o is int i)
{
}
// Over:
if (o is int)
{
var i = (int)o;
}
⚠ Yes
// Prefer:
if (o is string s)
{
}
// Over:
var s = o as string;
if(s != null)
{
}
ℹ Prefer Yes up to one single condition!
// Prefer:
string s = expr ? "hello" : "world";
// Over:
string s;
if(expr)
{
s = "hello";
}
else
{
s = "world";
}
ℹ Prefer Yes
// Prefer:
return expr ? "hello" : "world";
// Over:
if(expr)
{
return "hello";
}
else
{
return "world";
}
ℹ Prefer Yes, because it's new feature since C# 7
// Prefer:
public (string name, int age) GetCustomer()
{
}
// Over:
public Tuple<string,int> GetCustomer()
{
}
// Prefer:
(string name, int age) customer = GetCustomer();
var name = customer.name;
var age = customer.age;
// Over:
(string name, int age) customer = GetCustomer();
var name = customer.Item1;
var age = customer.Item2;
ℹ Prefer Yes
// Prefer:
void DoWork(CancellationToken cancellationToken = default) { }
// Over:
void DoWork(CancellationToken cancellationToken = default(CancellationToken)) { }
ℹ Prefer Yes
// Prefer:
var tuple = (age, name);
// Over:
var tuple = (age: age, name: name);
ℹ Prefer Yes
// Prefer:
var anon = new { age, name };
// Over:
var anon = new { age = age, name = name };
⚠ Yes
// Prefer:
int fibonacci(int n)
{
return n <= 1 ? n : fibonacci(n - 1) + fibonacci(n - 2);
}
// Over:
Func<int, int> fibonacci = null;
fibonacci = (int n) =>
{
return n <= 1 ? n : fibonacci(n - 1) + fibonacci(n - 2);
}
ℹ Prefer Yes
// Prefer:
value += 10;
// Over:
value = value + 10;
⚠ Yes
// Prefer:
var ch = value[^1];
// Over:
var ch = value[value.Length - 1];
⚠ Yes
// Prefer:
var sub = value[1..^1];
// Over:
var sub = value.Substring(1, value.Length - 2);
ℹ Prefer when on single line
class Customer
{
private int age;
public int GetAge() => age;
}
❌ Never
class Customer
{
private int age;
public Customer(int age)
{
this.age = age;
}
}
ℹ When on single line
public static ComlexNumber operator +(ComlexNumber c1, ComlexNumber c2)
=> new ComlexNumber(c1.Real + c2.Real, c1.Imaginary + c2.Imaginary);
ℹ When possible
class Customer
{
private int _age;
public int Age => _age;
}
ℹ When possible
class List<T>
{
private T[] _values;
public T this[int i] => _values[i];
}
⚠ When possible
class Customer
{
private int _age;
public int Age
{
get => _age;
set => _age = value;
}
}
When possible
Func<int, string> f = a => a.ToString();
ℹ When possible
class Customer
{
private int age;
public int GetAge()
{
return GetAgeLocal();
int GetAgeLocal() => age;
}
}
ℹ Discard
// Prefer:
_ = Computation(); // Unused value is explicitly assigned to discard
int x = 1;
// Over:
var unused = Computation(); // Unused value is explicitly assigned to an unused local
int x = 1;
// Over:
var x = Computation(); // Value assigned here is never used
int x = 1;
Discard
// Prefer:
_ = Computation();
// Over:
var unused = Computation();
// Over:
Computation();
ℹ Yes
// Prefer:
if (int.TryParse(value, out int i))
{
}
// Over:
int i;
if (int.TryParse(value, out i))
{
}
ℹ Yes
// Prefer:
var (name, age) = GetPersonTuple();
Console.WriteLine($"{name} {age}");
(int x, int y) = GetPointTuple();
Console.WriteLine($"{x} {y}");
// Over:
var person = GetPersonTuple();
Console.WriteLine($"{person.name} {person.age}");
var point = GetPointTuple();
Console.WriteLine($"{point.x} {point.y}");
⚠ Yes
// Prefer:
this.s = s ?? throw new ArgumentNullException(nameof(s));
// Over:
if (s == null)
throw new ArgumentNullException(nameof(s));
this.s = s;
⚠ Yes
// Prefer:
func?.Invoke(args);
// Over:
if (func != null)
{
func(args);
}
❌ YES!
// Prefer:
var v = x ?? y;
// Over:
var v = x != null ? x : y; // or
var v = x == null ? y : x;
❌ YES!
// Prefer:
var v = o?.ToString();
// Over:
var v = o == null ? null : o.ToString(); // or
var v = o != null ? o.ToString() : null;
⚠ Yes
// Prefer:
if (value1 is null)
return;
if (value2 is null)
return;
// Over:
if (object.ReferenceEquals(value1, null))
return;
if ((object)value2 == null)
return;
Outside namespace
// Prefer:
using System;
using System.Linq;
namespace Namespace
{
class Customer
{
}
}
// Over:
namespace Namespace
{
using System;
using System.Linq;
class Customer
{
}
}
⚠ Yes
// Prefer:
// '_value' can only be assigned in constructor
private readonly int _value = 0;
// Over:
// '_value' can be assigned anywhere
private int _value = 0;
❌ YES!
If a local function doesn't use any member from method body, just declare it as static!
void Method()
{
// Prefer:
static int fibonacci(int n)
{
return n <= 1 ? n : fibonacci(n - 1) : fibonacci(n - 2);
}
}
void Method()
{
// Over:
int fibonacci(int n)
{
return n <= 1 ? n : fibonacci(n - 1) : fibonacci(n - 2);
}
}
ℹ All methods
// Prefer:
public void M()
{
}
// Over:
public void M(int param)
{
}
This document is created to guide naming convensions in this project.
Context | Format | Samples |
---|---|---|
Resource Keys | PascalCase {Context}{SubContext}{Key} |
UsersNotFound AppSettingDialogError |
Json Keys | camelCase | { "title": "Hello World!", "isEnabled": true, numberOfCup: 19 } |
Endpont Routes | camelCase (Case In-Sensitive) |
/v1/app/123123/userProfiles/987 |
Class | PascalCase | .Net Defaults |
Variable | camelCase | .Net Defaults |
Property | PascalCase | .Net Defaults |
Method | PascalCase | .Net Defaults |
Field | camelCase | .Net Defaults |
Enum | PascalCase | .Net Defaults |
Attribute | PascalCase | .Net Defaults |
Constant | UPPERCASE_UNDERSCORE | .Net Defaults |
Events | PascalCase | .Net Defaults |