我有一个工厂类,用于创建带有循环引用的对象.我希望它们也是不变的(在某种意义上说).所以我使用以下技术,使用一种类型的闭包:
[<AbstractClass>]
type Parent() =
abstract Children : seq<Child>
and Child(parent) =
member __.Parent = parent
module Factory =
let makeParent() =
let children = ResizeArray()
let parent =
{ new Parent() with
member __.Children = Seq.readonly children }
[Child(parent); Child(parent); Child(parent)] |> children.AddRange
parent
Run Code Online (Sandbox Code Playgroud)
我比一种internal AddChild方法更喜欢这个,因为它有更强的不变性保证.也许它是神经质的,但我更喜欢关闭访问控制.
这个设计有什么陷阱吗?有没有更好的,也许不那么繁琐的方法来做到这一点?
使用只读属性之间有区别吗:
type T(arg) =
member x.M = arg
Run Code Online (Sandbox Code Playgroud)
并使用自动实现的属性:
type T(arg) =
member val M = arg
Run Code Online (Sandbox Code Playgroud)
假设arg没有副作用?有理由偏爱一个吗?
我有一个UserScope类似于TransactionScope它的类,即它将当前状态存储在本地线程中.这当然不适用于调用await,TransactionScope直到TransactionScopeAsyncFlowOption.NET 4.5.1中都没有添加.
我可以使用什么替代线程本地,以便UserScope在单线程和多线程场景中使用相同的?(如果我安装了4.5.1,我会反编译以查看TransactionScope它是如何做的.)这是我所拥有的简化版本:
class User {
readonly string name;
public User(string name) {
this.name = name;
}
public string Name {
get { return this.name; }
}
}
class UserScope : IDisposable {
readonly User user;
[ThreadStatic]
static UserScope currentScope;
public UserScope(User user) {
this.user = user;
currentScope = this;
}
public static User User {
get { return currentScope != null ? currentScope.user : null; …Run Code Online (Sandbox Code Playgroud) 是否有推荐的方法来模拟F#中的多个继承级别,可能是使用区分联合?
在C#中使用以下内容:
class Expr { }
class SourceExpr : Expr { }
class JoinExpr : SourceExpr { }
class TableExpr : SourceExpr { }
Run Code Online (Sandbox Code Playgroud)
我在F#中做到了这一点:
type SourceExpr =
| Join of JoinExpr
| Table of TableExpr
type Expr =
| Source of SourceExpr
| ...
Run Code Online (Sandbox Code Playgroud)
有没有更好的办法?这是否提供与继承相同的多态行为?
文档说:
F#为与类型IDelegateEvent兼容的非虚拟实例成员属性提供特殊状态,生成适当的.NET元数据以使该成员作为.NET事件显示给其他.NET语言.
但是,无论有没有CLIEvent属性,IDelegateEvent和IEvent的行为都是相同的.
我正在使用1.9.7.8.
为什么要使用OPENXML而不是OPENROWSET(BULK'file',SINGLE_BLOB)并转换为xml数据类型?
基于这个问题的讨论,任何人都可以提供代码或代码链接,显示NumericLiteralX模块的完整实现(例如这个)吗?我特别感兴趣的是有效实现FromInt32/ 64用于NumericLiteralX促进通用数字运算的模块.这是从上述问题中得出的可能效率低下的实现:
module NumericLiteralG =
let inline FromZero() = LanguagePrimitives.GenericZero
let inline FromOne() = LanguagePrimitives.GenericOne
let inline FromInt32 (n:int) =
let one : ^a = FromOne()
let zero : ^a = FromZero()
let n_incr = if n > 0 then 1 else -1
let g_incr = if n > 0 then one else (zero - one)
let rec loop i g =
if i = n then g
else …Run Code Online (Sandbox Code Playgroud) 在C#中给出以下CRTP类型:
public abstract class DataProviderBase<TProvider>
where TProvider : DataProviderBase<TProvider> { }
Run Code Online (Sandbox Code Playgroud)
我如何在F#中获得其泛型类型定义?
let typeDef = typedefof<DataProviderBase<_>>
Run Code Online (Sandbox Code Playgroud)
产生错误:
对类型推断变量应用默认类型"DataProviderBase <'a>"时,键入约束不匹配.统一''a'和'DataProviderBase <'时,结果类型将是无限的'a>考虑添加更多类型约束
在C#中,它将是:
var typeDef = typeof(DataProviderBase<>);
Run Code Online (Sandbox Code Playgroud)
我找到了一个解决方法:
[<AbstractClass>]
type DummyProvider() =
inherit DataProviderBase<DummyProvider>()
let typeDef = typeof<DummyProvider>.BaseType.GetGenericTypeDefinition()
Run Code Online (Sandbox Code Playgroud)
有没有其他方法可以做到这一点,没有额外的类型?
由于.NET数组是协变的,因此以下代码可在C#中工作:
var strArray = new string[0];
object[] objArray = strArray;
Run Code Online (Sandbox Code Playgroud)
在F#中,给定数组,'T[]将其转换为的最佳方法是什么obj[],而无需重新创建数组(例如Array.map box)?我正在使用(box >> unbox),但感觉很草率。
是否有更短的方式来创建一个IDictionary<_,obj>,可能没有拳击每个值?这就是我所拥有的.
let values =
[ "a", box 1
"b", box "foo"
"c", box true ]
|> dict
Run Code Online (Sandbox Code Playgroud)
Dictionary<_,obj>.Add 可以在没有拳击的情况下进行调用,但我无法找到一种方法来使用它比我的更短.
我希望除了定义拳击操作员之外的其他东西.
根据Brian的建议,这是一种方法,但它有自己的问题.
let values =
Seq.zip ["a"; "b"; "c"] ([1; "foo"; true] : obj list) |> dict
Run Code Online (Sandbox Code Playgroud) f# ×8
.net ×1
arrays ×1
async-await ×1
c# ×1
class-design ×1
closures ×1
covariance ×1
crtp ×1
f#-3.0 ×1
generics ×1
immutability ×1
literals ×1
reflection ×1
sql-server ×1
xml ×1